Upload
ksapp412
View
228
Download
0
Embed Size (px)
Citation preview
7/30/2019 Operation Models Slides
1/147
7/30/2019 Operation Models Slides
2/147
LEVEL 1
7/30/2019 Operation Models Slides
3/147
INSTAPHOTO - WHERE WE LEFT IT
7/30/2019 Operation Models Slides
4/147
WHY MODELS?
Controllers tell Views how
to display data
Views display app data
Models handle app data
from Models
Models make it easy to organize and store data in an a
7/30/2019 Operation Models Slides
5/147
DATA IN INSTAPHOTO - THE CURRENT APPROA
Controllers drawing Views using data from a Controller
data passed whencell tapped
Thats no g
FeedTableVC PhotoVC
View View
7/30/2019 Operation Models Slides
6/147
DATA IN INSTAPHOTO - THE MVC WAY
Controllers drawing Views using data from a Model
Controller
asks for data
Model provides
data object
model instancepassed when celltapped
FeedTableVC PhotoVC
View View
Model
7/30/2019 Operation Models Slides
7/147
CREATING A MODEL CLASS IN XCODE
7/30/2019 Operation Models Slides
8/147
CLASS HIERARCHY OF A MODEL
NSObject is the base parent Class of almost everything
@interface Place : NSObject
NSObject
UIResponder
UIViewController
UITabBarController UINavigationController
Place
Class Name Parent Class
Model is a subclassof NSObject
7/30/2019 Operation Models Slides
9/147
PLANET HIG
Straight to the TOP
of the APP STORE!
7/30/2019 Operation Models Slides
10/147
PLANET HIG CLASS STRUCTURE
CityViewControlPlaceTableViewController InterestingPlacesTableViewController
AppDelegate
7/30/2019 Operation Models Slides
11/147
PLACE MODEL @INTERFACE AND @IMPLEMEN
Place.h
Place.m
singular name, not plu
#import"Place.h"
@implementation Place
@end
#import
@interface Place : NSObject
@end
7/30/2019 Operation Models Slides
12/147
DECLARING PLACE MODEL @PROPERTY VARIA
#import
@end
Place.h
@interface Place : NSObject
@property (strong, nonatomic)NSString*name;
@property (strong, nonatomic)NSString*description;NSStr
7/30/2019 Operation Models Slides
13/147
IMPLEMENTING INIT IN THE PLACE MODEL
#import"Place.h"
@end
Place.m
@implementation Place
selfrefers to an instance of this Class (Place)superrefers to the parent Class (NSObject)
NSOb
Place
-(id)i[super init]
self supe
- (id)init {
self = [superinit];
return self;
}
7/30/2019 Operation Models Slides
14/147
MODEL OBJECT INSTANTIATION
PlaceViewController.m
console output
> name is: Taco Cantina> description is: Tasty tacos.
Access valuesor message pa
Place *aPlace = [[Place alloc] init];
aPlace.name = @"Taco Cantina";aPlace.description = @"Tasty tacos.";
NSLog(@"name is: %@", [aPlace name]);NSLog(@"description is: %@", aPlace.description);
7/30/2019 Operation Models Slides
15/147
INSTANTIATE MULTIPLE OBJECTS WITH ONE M
PlaceViewController.m
Place *placeOne = [[Place alloc] init];
Place *placeTwo = [[Place alloc] init];Place *placeThree = [[Place alloc] init];
@"Taco Cantina"
@"Tasty tacos."
@"Fish Town"
@"Scrumptious sushi."
@"Envy Labs"
@"Enviable educators."
placeOne.name =placeTwo.name =placeThree.name =
placeOne.description =placeTwo.description =placeThree.description =
;;;
;;;
Thats a l
of repeti
7/30/2019 Operation Models Slides
16/147
OBJECT INSTANTIATION WITH A CONVENIENCE INIT
PlaceViewController.m
Place *placeOne = [[Place alloc] init
Place *placeTwo = [[Place alloc] init
Place *placeThree = [[Place alloc] init
];
@"Taco Cantina"
@"Fish Town"
@"Envy Labs"
@"Tasty tacos."
@"Scrumptious sushi
@"Enviable educat
initWithName:description: is called a convenience initiali
WithName:
description:
WithName:description:
WithName:description:
7/30/2019 Operation Models Slides
17/147
DECLARING A CONVENIENCE INITIALIZER
@end
Place.h
- (id)initWithName:(NSString *)aName
description:(NSString *)aDescription;
#import
@interface Place : NSObject
@property (strong, nonatomic)NSString*name;
@property (strong, nonatomic)NSString*description;
7/30/2019 Operation Models Slides
18/147
IMPLEMENTING A CONVENIENCE INITIALIZER
Place.m
{
PlaceViewController.m
Place *placeOne = [[Place alloc] initWithName:@"Taco Cantina"
description:@"Tasty tacos."];
local argumentsmodel properties
verify [superintrying to set prop
- (id)initWithName:(NSString *)aName
description:(NSString *)aDescription
self = [superinit];if(self) {
self.name = aName;self.description = aDescription;
}return self;
}
THE PROBLEM WITH INIT
7/30/2019 Operation Models Slides
19/147
Place *placeOne = [[Place alloc] initWithName:@"Taco Cantina"
description:@"Tasty tacos."];
THE PROBLEM WITH INIT
PlaceViewController.m
Place *placeTwo = [[Place alloc] init];
NSLog(@"placeOne name: %@", placeOne.name);
NSLog(@"placeTwo name: %@", placeTwo.name);
Console output> placeOne name: Taco Cantina
> placeTwo name: nil
What COUNT
NIL IN????
CONVERTING TO A DESIGNATED INITIALIZER
7/30/2019 Operation Models Slides
20/147
CONVERTING TO A DESIGNATED INITIALIZER
Place.m
@end
- (id)initWithName:(NSString *)aName
description:(NSString *)aDescription {
self = [superinit];
if(self) { self.name = aName; self.description = aDescription;
}return self;
}
- (id)init {self = [self initWithName:@"defaultName"
description:@"defaultDescription"];return self;
}
USING A DESIGNATED INITIALIZER
7/30/2019 Operation Models Slides
21/147
USING A DESIGNATED INITIALIZER
PlaceViewController.m
Console output
> placeOne name: Taco Cantina> placeTwo name: defaultName
init triggers the designated initializerinitWithName:description:
Place *placeOne = [[Place alloc] initWithName:@"Taco Cantina"
description:@"Tasty tacos."];Place *placeTwo = [[Place alloc] init];
NSLog(@"placeOne name: %@", placeOne.name);
NSLog(@"placeTwo name: %@", placeTwo.name);
MODEL CONVENTIONS
7/30/2019 Operation Models Slides
22/147
MODEL CONVENTIONS
@property memory management
@property (strong, nonatomic);
Arguments should start with a, an, or the
- (id)initWithCity:(NSString *)city address:(NSString *)address
- (id)initWithCity:(NSString *)aCity address:(NSString *)anAddres
Long method names on multiple lines lined up by colons
- (id)initWithCity:(NSString *)aCity address:(NSString *)anAddres
- (id)initWithCity:(NSString *)aCity address:(NSString *)anAddress
7/30/2019 Operation Models Slides
23/147
LEVEL 2
CITYVIEWCONTROLLER IN PLANET HIG
7/30/2019 Operation Models Slides
24/147
CITYVIEWCONTROLLER IN PLANET HIG
ViewCityViewController
nameLabel stateLabel p
Lets see where this city data comes f
FETCHING THE CITY DATA FOR PLANET HIG
7/30/2019 Operation Models Slides
25/147
FETCHING THE CITY DATA FOR PLANET HIG
2 NSStrings
1 NSNumber
1 NSDictionary containing:
CityViewController.h
@property (strong, nonatomic) NSDictionary *cityData;
http://example.com/cityData.json
old way
{
"name": "Orlando","state": "Florida",
"population": 238300
}
FETCHING CITYDATA JSON WITH AFNETWORK
http://remote.com/cityData.JSONhttp://remote.com/cityData.JSON7/30/2019 Operation Models Slides
26/147
FETCHING CITYDATA.JSON WITH AFNETWORK
self.cityData = JSON;
NSLog(@"NSError: %@",error.localizedDescription);
}];
[operation start];
AFJSONRequestOperation *operation = [AFJSONRequestOperationJSONRequestOperationWithRequest:requestsuccess:^(NSURLRequest *request, NSHTTPURLResponse *response, id
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response,
NSError *error, id J
[self dataRetrieved];
CityViewController.m
NSURL *url = [[NSURL alloc] initWithString:@"http://codeschool.com/c
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
USING THE JSON RESPONSE IN DATARETRIEVED
http://codeschool.com/placeData.jsonhttp://codeschool.com/placeData.json7/30/2019 Operation Models Slides
27/147
USING THE JSON RESPONSE IN DATARETRIEVED
self.cityData = JSON;
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:requestsuccess:^(NSURLRequest *request, NSHTTPURLResponse *response, id
}[self dataRetrieved];
...
- (void)dataRetrieved {
NSLog(@"City name is: %@", self.cityData[@"name"]);NSLog(@"City state is: %@", self.cityData[@"state"]);
NSLog(@"City population is: %@", self.cityData[@"population"]);
}
This seems like a go
place For a Model
CityViewController.m
LETS CREATE THE CITY MODEL
7/30/2019 Operation Models Slides
28/147
LET S CREATE THE CITY MODEL
#import
@interface City : NSObject
@property (strong, nonatomic)NSString*name;@property (strong, nonatomic)NSString*state;
@property (strong, nonatomic)NSNumber*population;
@end
City.h
#import"City.h"@implementation City
- (id)init {
self = [superinit];
return self;
}
@end
City.m
PUTTING THE JSON RESPONSE IN A MODEL
7/30/2019 Operation Models Slides
29/147
PUTTING THE JSON RESPONSE IN A MODEL
self.city.name = JSON[@"name"];
AFJSONRequestOperation *operation = [AFJSONRequestOperationJSONRequestOperationWithRequest:requestsuccess:^(NSURLRequest *request, NSHTTPURLResponse *response, id J
}
[self dataRetrieved];
...
self.city.state = JSON[@"state"];
self.city.population = JSON[@"population"];
CityViewController.h
@property (strong, nonatomic) City *city;
self.city = [[City alloc] init];
CityViewController.m
Seems like we can improv
#import"City.h"
NSLog(@"City name is: %@", self.city.name);
NSLog(@"City state is: %@", self.city.state);
NSLog(@"City population is: %@", self.city.population);
- (void)dataRetrieved {
}
INITIALIZING MODEL DATA IN A CONTROLLER
7/30/2019 Operation Models Slides
30/147
INITIALIZING MODEL DATA IN A CONTROLLER
Controller is respfetching data, no
PROBLEM
View
City
CityViewController
INITIALIZING MODEL DATA IN A MODEL
7/30/2019 Operation Models Slides
31/147
INITIALIZING MODEL DATA IN A MODEL
Model is responsi
fetching data, notController.
initWithJSON:
SOLUTION
convenienceinitializer
I love convenien
solutions
City
View
CityViewController
DECLARING AN INITWITHJSON CONVENIENCE INITIALIZER
7/30/2019 Operation Models Slides
32/147
DECLARING AN INITWITHJSON CONVENIENCE INITIALIZER
City.h
- (id)initWithJSON;
#import@interface City : NSObject
@property (strong, nonatomic)NSString*name;
@property (strong, nonatomic)NSString*state;
@property (strong, nonatomic)NSNumber*population;
@end
IMPLEMENTING INITWITHJSON IN THE CITY M
7/30/2019 Operation Models Slides
33/147
IMPLEMENTING INITWITHJSON IN THE CITY M
#import"City.h"
@end
City.m
@implementation City
- (id)init { self = [superinit];
return self;}
AFJSONRequestOperation *operation = [AFJSONRequestOperation
self = [superinit];if(self) {
} return self;}
- (id)initWithJSON {
SETTING MODEL PROPERTIES USING INITWITH
7/30/2019 Operation Models Slides
34/147
SETTING MODEL PROPERTIES USING INITWITH
City.m
NSLog(@"NSError: %@",error.localizedDescription);
}];
[operation start];
success:^(NSURLRequest *request, NSHTTPURLResponse *respon
failure:^(NSURLRequest *request, NSHTTPURLResponse *responsNSError *error
}
self.name = JSON[@"name"];
self.state = JSON[@"state"]; self.population = JSON[@"population"];
AFJSONRequestOperation *operation = [AFJSONRequestOperationJSONRequestOperationWithRequest:request
self = [superinit];
if(self) {
} return self;
}
- (id)initWithJSON {
TESTING INITWITHJSON
7/30/2019 Operation Models Slides
35/147
TESTING INITWITHJSON
self.city = [[Cityalloc] initWithJSON];
NSLog(@"state is: %@", self.city.state);
NSLog(@"population is is: %d", self.city.population);
CityViewController.m
CityViewController.h
#import"City.h"
@property (strong, nonatomic) City *city;
nil
nil
What In the NIL Is GOING ON?
WHY INITWITHJSON ALONE IS NOT ENOUGH
7/30/2019 Operation Models Slides
36/147
WHY INITWITHJSON ALONE IS NOT ENOUGH
initWithJSON:
View
City
CityViewController1. Controllerasks for Model
3a. Model
returns instance
2. Controllcontinues
3b. View di
No guarantee that 3a happens before 3b
USING NOTIFICATIONS TO DELAY EXECUTION
7/30/2019 Operation Models Slides
37/147
initWithJSON:
View
City
CityViewController1. Controllerasks for Model
3. Model posts notificationwhen ready
2. Con
notifi
5. Viedata
NSNotificationCenter
4. Consendswhenis hea
NSNOTIFICATIONCENTER
7/30/2019 Operation Models Slides
38/147
NSNotificationCenter
postednotification
subscribes
notificationlistener
notificationlistener
notificationlistener
notifies
POSTING AND LISTENING FOR NOTIFICATIONS
7/30/2019 Operation Models Slides
39/147
[[NSNotificationCenterdefaultCenter]
addObserver:self selector:@selector(dataRetrieved
name:@"initWithJSONFinishedL
object:nil];
[[NSNotificationCenterdefaultCenter]
postNotificationName:@"initWithJSON object:nil];
Sending a Notification
Listening for a Notification
ObserverInstance that is listening
SelectorMethod to call whennotification is heard
Name
Unique notification nameObjectCan listen for notificationsfrom a specific object
POSTING A NOTIFICATION IN INITWITHJSON
7/30/2019 Operation Models Slides
40/147
J
City.m ( inside initWithJSON )
success:^(NSURLRequest *request, NSHTTPURLResponse *respon
}
self.name = JSON[@"name"]; self.state = JSON[@"state"];
self.population = JSON[@"population"];
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
[[NSNotificationCenterdefaultCenter]
postNotificationName:@"initWithJSONFinishedLoadin
object:nil];
Post a notification in the last line of the success block
LISTENING FOR A NOTIFICATION IN A CONTRO
7/30/2019 Operation Models Slides
41/147
CityViewController.m
- (void)viewDidLoad {
Florida
238300
- (void)dataRetrieved {
NSLog(@"City state is: %@", self.city.state);
NSLog(@"City population is: %@", self.city.population);
}
self.city = [[Cityalloc] initWithJSON];
[[NSNotificationCenterdefaultCenter]
addObserver:self
selector:@selector(dataRetrieved)
name:@"initWithJSONFinishedLoading"
object:nil];
MAKING INITWITHJSON THE DESIGNATED INIT
7/30/2019 Operation Models Slides
42/147
J
#import"City.h"
@end
City.m
@implementation City
AFJSONRequestOperation *operation = [AFJSONRequestOperation
- (id)initWithJSON {
self = [superinit];if(self) {
}
return self;}
- (id)init {
self = [selfinitWithJSON];return self;
}
CALLING INIT INSTEAD OF INITWITHJSON
7/30/2019 Operation Models Slides
43/147
self.city = [[Cityalloc] init];
[[NSNotificationCenterdefaultCenter]
addObserver:self
selector:@selector(dataRetrieved)
name:@"initWithJSONFinishedLoading"
object:nil];
CityViewController.m
- (void)viewDidLoad {
}
Notification n
OHyeaaaaaaa
Florid
238300
- (void)dataRetrieved {
NSLog(@"City state is: %@", self.city.state);
NSLog(@"City population is: %@", self.city.population);
}
INSTAPHOTOS USER.H BEFORE PHOTO REFACT
7/30/2019 Operation Models Slides
44/147
User.h
#import
@interface User : NSObject
@property (strong, nonatomic)NSString*firstName;
@property (strong, nonatomic)NSString* ;profilePhoto@property (strong, nonatomic)NSString* ;profilePhotoThumbnail@property (strong, nonatomic)NSString*biography;@property (strong, nonatomic)NSString*memberSince;
@end
- (void)initWithJSON;
@property (strong, nonatomic)NSString*lastName;
@property (strong, nonatomic)NSString*location;
INSTAPHOTOS USER.H AFTER PHOTO REFACTO
7/30/2019 Operation Models Slides
45/147
User.h
#import
@end
@interface User : NSObject
@property (strong, nonatomic)Photo* ;profilePhoto
#import"Photo.h"
@property (strong, nonatomic)NSString*biography;@property (strong, nonatomic)NSString*memberSince;
- (void)initWithJSON;
CityViewCo
User
@property (strong, nonatomic)NSString*firstName;
@property (strong, nonatomic)NSString*lastName;
@property (strong, nonatomic)NSString*location;
INSTAPHOTOS USER MODEL PROFILEPHOTO
7/30/2019 Operation Models Slides
46/147
User.m
AFJSONRequestOperation *operation = [AFJSONRequestOperation
- (id)initWithJSON { self = [superinit];
if(self) {
This data should be in a Photo Model
self.firstName = JSON[@"firstName"]; self.lastName = JSON[@"lastName"]; self.location = JSON[@"location"];
self.biography = JSON[@"biography"]; self.memberSince = JSON[@"memberSince"];
self.profilePhotoself.profilePhotoThumbnail
==JSON[@"profilePhoto"]JSON[@"profilePhotoThumb
;
...
...
7/30/2019 Operation Models Slides
47/147
LEVEL 3
PLANET HIG STRUCTURE SO FAR
7/30/2019 Operation Models Slides
48/147
CityViewControllePlaceTableViewController InterestingPlacesTableViewController
AppDelegate
Lets see how this table view gets data
EXAMINING PLACEDATA.JSON
7/30/2019 Operation Models Slides
49/147
an NSArray co
NSDictionary
http://example.com/placeData.json
[
{
"name": "Taco Cantina",
"description": "Tasty tacos."
},
{
"name": "Fish Town",
"description": "Scrumptious sushi."
},{
"name": "Envy Labs",
"description": "Enviable educators."
}
]
each NSDictio
contains 2 NSS
MAKING AN AFNETWORKING REQUEST FOR PLACEDA
http://example.com/placeData.jsonhttp://example.com/placeData.json7/30/2019 Operation Models Slides
50/147
PlaceTableViewController.h
@property (strong, nonatomic) NSArray *places;
PlaceTableViewController.m
NSURL *url = [[NSURL alloc] initWithString:@"http://example.com/place
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id J
self.places = JSON;} failure:^(NSURLRequest *request, NSHTTPURLResponse *response,
NSError *error, id JSON) {
NSLog(@"NSError: %@",error.localizedDescription);
}];
[operation start];
This approach isnt creating Place
MAKING PLACE OBJECTS
http://codeschool.com/placeData.jsonhttp://codeschool.com/placeData.json7/30/2019 Operation Models Slides
51/147
PlaceTableViewController.h
#import"Place.h"
@property (strong, nonatomic) NSArray *places;
PlaceTableViewController.mAFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id J
}
self.places = @[place1, place2, place3];
Not efficient - what if there are 20 objects?
Place*place1 = [[Placealloc]initWithName:JSON[0]["name"]
description:JSON[0]["descripti
Place*place2 = [[Placealloc]initWithName:JSON[1]["name"]
description:JSON[1]["descripti
Place*place3 = [[Placealloc]initWithName:JSON[2]["name"]
description:JSON[2]["descripti
USING FAST ENUMERATION
7/30/2019 Operation Models Slides
52/147
0 1 2 3
Fluffy Pepper Whiskers HiggieCat
Console OutpNSArray *catNames> Cat name is
> Cat name is
> Cat name is
> Cat name is
a new Object that is local to theenumeration loop!
The set/array you areenumerating through
Now this is gospeed things ufor (NSString *catName in catNames) {
NSLog(@"Cat name is: %@",catName);
}
CREATE NSARRAY OF MODEL OBJECTS WITH FAST ENUM
7/30/2019 Operation Models Slides
53/147
for (NSDictionary *oneDictionary in JSON) {
Place *newPlace = [[Placealloc] initWithName:oneDictionary[@" description:oneDictionary[@"
}
0 1 2
Place object 1 Place object 2 Place object 3
NSArray *places
Our goal
[self.placesaddObject:newPlace];
Cant modify an NSArray
LIST OF MUTABLE CLASSES
7/30/2019 Operation Models Slides
54/147
Immutable Classes Mutable Classes
NSString NSMutableString
NSSet NSMutableSet
NSArray NSMutableArray
NSDictionary NSMutableDictionary
NSData NSMutableData
NSURLRequest NSMutableURLRequest
Mutable Class objects can be modified after they are inst
ADDING OBJECTS TO AN NSARRAY VIA A TEMPORARY NSMUTA
7/30/2019 Operation Models Slides
55/147
for (NSDictionary *oneDictionary in JSON) {
Place *newPlace = [[Placealloc] initWithName:oneDictionary[@" initWithDescription:oneDictionary[@"
}
0 1 2
Place object 1 Place object 2 Place object 3
NSArray *places
NSMutableArray *tempArray = [[NSMutableArrayalloc] init];
[tempArray addObject:newPlace];
self.places = [[NSArrayalloc] initWithArray:tempArray];
creating an immutable version with an existing mutable array
We can add objects to mut
PLACETABLEVIEWCONTROLLER UITABLEVIEW M
7/30/2019 Operation Models Slides
56/147
Easy! Weve Done this
a few times before
PlaceTableViewController.m
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (void) tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
}
UITABLEVIEW NUMBEROFROWSINSECTION: FROM PLACES @
7/30/2019 Operation Models Slides
57/147
}
PlaceTableViewController.m
returnself.places.count;
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- (void) tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
}
UITABLEVIEW CELLFORROWATINDEXPATH: FROM PLACES @
7/30/2019 Operation Models Slides
58/147
PlaceTableViewController.m
UITableViewCell *cell = [tableView dequeueReusableCellWithIdenti
if(cell == nil) {cell = [[UITableViewCellalloc] initWithStyle:UITableViewCel
reuseIdentifier:@"pCell"];}
return cell;
Incorrect syntax
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
}
.name;cell.textLabel.text = self.places[indexPath.row]
THE CORRECT WAY TO ACCESS MODEL OBJECT PRO
7/30/2019 Operation Models Slides
59/147
PlaceTableViewController.m
Correct syntax using message
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdenti
if(cell == nil) {cell = [[UITableViewCellalloc] initWithStyle:UITableViewCel
reuseIdentifier:@"pCell"];}
return cell;
}
]name ;cell.textLabel.text = self.places[indexPath.row][
PUSH A PLACE MODEL INSTANCE WHEN A CELL IS
7/30/2019 Operation Models Slides
60/147
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
PlaceViewController *placeVC = [PlaceViewController alloc] init]
placeVC.place = self.places[indexPath.row];
[self.navigationControllerpushViewController:placeVC animated:Y
PlaceTableViewController Cell PlaceV
Place Model instance passed when cell is tapped
- (void) tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
PlaceTableViewController.m
PLACETABLEVIEWCONTROLLER
7/30/2019 Operation Models Slides
61/147
DECLARING A PLACE @PROPERTY VARIABLE IN PLACEVIEWCO
7/30/2019 Operation Models Slides
62/147
PlaceViewController.h
@property (strong, nonatomic) Place *place;
@interface PlaceViewController:UIViewController
@property (strong, nonatomic) UILabel *placeNameLabel;
#import"Place.h"
PlaceViewController Place
@property (strong, nonatomic) UILabel *placeDescriptionLabel;
IMPLEMENTING SUBVIEWS IN PLACEVIEWCONTR
Pl Vi C t ll
7/30/2019 Operation Models Slides
63/147
PlaceViewController.m
- (void)viewDidLoad {
self.placeNameLabel = [[UILabelalloc] init];
self.placeNameLabel.frame = CGRectMake(20,40,280,40);[self.viewaddSubview:self.placeNameLabel];
self.placeDescriptionLabel = [[UILabelalloc] init];
self.placeDescriptionLabel.frame = CGRectMake(20,100,280,20);
[self.viewaddSubview:self.placeDescriptionLabel];
}
- (void)viewWillAppear:(BOOL)animated {
self.placeNameLabel.text = self.place.name;
self.placeDescriptionLabel.text=self.place.description;
}
create data containers in viewDidLoad
set data in containers in viewWillAppear
PUSHING TO PLACEVIEWCONTROLLER
7/30/2019 Operation Models Slides
64/147
DECLARING @PROPERTY VARIABLES IN CITYVIEWCON
CityViewController h
7/30/2019 Operation Models Slides
65/147
CityViewController.h
@property (strong, nonatomic) City *city;
@interface CityViewController : UIViewController
@property (strong, nonatomic) UILabel *cityNameLabel;
#import"City.h"
CityViewController City
@property (strong, nonatomic) UILabel *cityStateLabel;
@property (strong, nonatomic) UILabel *cityPopulationLabel;
like
did w
IMPLEMENTING SUBVIEWS IN CITYVIEWCONT
7/30/2019 Operation Models Slides
66/147
CityViewController.m
- (void)viewDidLoad {
self.cityNameLabel = [[UILabelalloc] init];
self.cityNameLabel.frame = CGRectMake(20,40,280,40);
[self.viewaddSubview:self.cityNameLabel];
}
- (void)viewWillAppear:(BOOL)animated {
self.cityNameLabel.text = self.city.name;
}
Repeat for state and population data properties
CITYVIEWCONTROLLER
7/30/2019 Operation Models Slides
67/147
PLANET HIG STRUCTURE SO FAR
A D l t
7/30/2019 Operation Models Slides
68/147
CityViewPlaceTableViewController
PlaceViewController
InterestingPlacesTableViewController
AppDelegate
7/30/2019 Operation Models Slides
69/147
LEVEL 4
ADDING THE ABILITY TO TAKE NOTES ABOUT A
7/30/2019 Operation Models Slides
70/147
It really is a useful
ADDING A NOTES @PROPERTY TO THE CITY MO
Cit h
7/30/2019 Operation Models Slides
71/147
#import
@end
City.h
@interface City : NSObject
@property (strong, nonatomic)NSString*name;
- (id)initWithJSON;
@property (strong, nonatomic)NSString*state;
@property (strong, nonatomic)NSNumber*population;
@property (strong, nonatomic)NSString*notes;
INITIALIZING THE DEFAULT VALUE OF NOTES IN THE CI
City m
7/30/2019 Operation Models Slides
72/147
@end
@implementation City
- (id)init { self = [self initWithJSON];
}
- (id)initWithJSON { self = [selfinit];
if(self) { ...
self.notes = @"no notes yet";...
}
return self;}
because the JSON file dohave any notes data
City.m
ADDING A UILABEL AND UITEXTFIELD FOR NOT
CityViewController.h
7/30/2019 Operation Models Slides
73/147
y
@property (strong, nonatomic)UILabel*notesLabel;
CityViewController.m
- (void)viewDidLoad {
self.notesLabel = [[UILabelalloc]init];
self.notesLabel.frame = CGRectMake(20,160,280,40);
}
@property (strong, nonatomic)UITextField*notesField;
@property (strong, nonatomic)City*city;
self.notesField = [[UITextFieldalloc]init];
self.notesField.frame = CGRectMake(15,220,290,30);
self.notesLabel.text = self.city.notes;
City *city=[[Cityalloc]init];
EDITING TEXT IN PLANET HIG
7/30/2019 Operation Models Slides
74/147
UITextField
ACCESSING THE TEXT IN UITEXTFIELD
Setting the text
7/30/2019 Operation Models Slides
75/147
Setting the text
self.notesField.text = @"Hi Jon!";
Getting the text
NSLog(@"%@",self.notesField.text);
Just like a UILabel that
you can edit!
LIST OF KEYBOARDTYPE VALUES UIKeyboardT
7/30/2019 Operation Models Slides
76/147
UIKeyboardTypeASCIICapable
UIKeyboardTypeNumbersAndPunctuation
UIKeyboardTypeURL
UIKeyboardTypeNumberPad
UIKeyboardTypePhonePad
UIKeyboardTypeNamePhonePadUIKeyboardTypeEmailAddress
UIKeyboardTypeDecimalPad
UIKeyboardTypeTwitter
UIKeyboardTypeAlphabet
UIKeyboardT
UIKeyboardT
self.notesField.keyboardType = UIKeyboardTypeDefault;
Other keyboard types
LIST OF UITEXTFIELD BORDER STYLES
7/30/2019 Operation Models Slides
77/147
self.notesField.borderStyle = UITextBorderStyleRoundedRect;
Border StylesUITextBorderStyleNone
UITextBorderStyleLine
UITextBorderStyleBezel
UITextBorderStyleRoundedRect
MAKING THE KEYBOARD GO AWAY
7/30/2019 Operation Models Slides
78/147
Dismissing the keyboard
requires code from the
UITextFieldDelegate Clas
Tapping return shouldmake the keyboard goaway
UITEXTFIELDDELEGATE METHODS
7/30/2019 Operation Models Slides
79/147
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
Runs when the Return key is tapped
- (BOOL)textFieldDidBeginEditing:(UITextField *)textField;
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;
- (BOOL)textFieldDidEndEditing:(UITextField *)textField;
- (BOOL) textField:(UITextField *)textFieldshouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
- (BOOL)textFieldShouldClear:(UITextField *)textField;
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
GETTING TEXTFIELDSHOULDRETURN: IN CITYVIEWCON
UITextFieldDelegate
7/30/2019 Operation Models Slides
80/147
CityViewController
Protocols are a way to get
methods from one Class
into another
UITextFieldDelegate
SETTING UP THE UITEXTFIELDDELEGATE PROTO
CityViewController.h
7/30/2019 Operation Models Slides
81/147
y
@interface CityViewController:UIViewController
7/30/2019 Operation Models Slides
82/147
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
}
// 1. Update the City Model object with the text in notesFiel
// 2. Make the keyboard go away
CityViewController.m
self.city.notes = self.notesField.text;
[textField resignFirstResponder];
returnYES;
WHICH VIEW IS THE FIRST RESPONDER?
ViCit Vi C t ll
7/30/2019 Operation Models Slides
83/147
notesField is the F
Responder when t
keyboard is onscre
ViewCityViewController
notesLabel notesField
WHICH VIEW IS THE FIRST RESPONDER?
ViewCityViewController
7/30/2019 Operation Models Slides
84/147
notesField is no lo
First Responder w
keyboard is dismis
ViewCityViewController
notesLabel notesField
PROBLEM: THE UITEXTFIELD IS IN CITYVIEWCONT
7/30/2019 Operation Models Slides
85/147
ViewCityViewController
notesLabel notesField
SOLUTION: MOVE THE UITEXTFIELD TO ANOTHER CON
7/30/2019 Operation Models Slides
86/147
EditNoteViewController CityViewController View
notesLabel
ADD A UIBUTTON TO SWITCH TO EDITNOTEVIEWCON
CityViewController.m
7/30/2019 Operation Models Slides
87/147
- (void)viewDidLoad {
}
UIButton *editButton = [UIButtonbuttonWithType:UIButtonTypeRound
editButton.frame = CGRectMake(20,220,280,50);
[editButton setTitle:@"Edit Note"forState:UIControlStateNormal]
[self.viewaddSubview:editButton];
[editButton addTarget:self
forControlEvents:UIControlEventTouchUpInside];
action:@selector(editPressed)
}
- (void)editPressed {
EditNoteViewController *editNoteVC = [[EditNoteViewControllerall
[self.navigationControllerpushViewController:editNoteVC animated
editNoteVC.city = self.city;
DECLARING @PROPERTY VARIABLES IN EDITNOTEVIEWCO
EditNoteViewController.h
7/30/2019 Operation Models Slides
88/147
@interface EditNoteViewController:UIViewController
7/30/2019 Operation Models Slides
89/147
- (void)viewWillAppear:(BOOL)animated {
}
self.notesField.delegate = self;
self.notesField.text = self.city.notes;
- (void)viewDidLoad {
}
self.notesField = [[UITextFieldalloc]init];
self.notesField.frame = CGRectMake(15,50,290,30);
self.city=[[Cityalloc]init];
CREATE A UIBUTTON TO GET BACK TO CITYVIEWCON
EditNoteViewController.m
7/30/2019 Operation Models Slides
90/147
- (void)viewDidLoad {
}
UIButton *saveButton = [UIButtonbuttonWithType:UIButtonTypeRoun
saveButton.frame = CGRectMake(15,100,290,50);
[saveButton setTitle:@"Save Note"forState:UIControlStateNormal]
[self.viewaddSubview:saveButton];
[saveButton addTarget:selfaction:@selector(savePressed)
forControlEvents:UIControlEventTouch
}
- (void)savePressed {
[self.navigationControllerpopViewControllerAnimated:YES];
self.city.notes = self.notesField.text;
EDITNOTEVIEWCONTROLLER DE
7/30/2019 Operation Models Slides
91/147
PUSHING EDITNOTEVC ONTO THE NAVIGATION S
CityViewController.m
7/30/2019 Operation Models Slides
92/147
}
- (void)editPressed {
EditNoteViewController *editNoteVC = [[EditNoteViewControlleral
[self.navigationControllerpushViewController:editNoteVC animated
editNoteVC.city = self.city;
Only Use a Navigationcontroller stack if
need to move through a hierarchy of view
OPENING EDITNOTEVC AS A MODAL VIEW
CityViewController.m
7/30/2019 Operation Models Slides
93/147
[selfpresentViewController:editNoteVCanimated:YEScompletion:n
- (void)editPressed {
EditNoteViewController *editNoteVC = [[EditNoteViewControlleral
editNoteVC.city = self.city;
}
MAKING A MODAL VIEW GO AWAY
EditNoteViewController.m
7/30/2019 Operation Models Slides
94/147
}
- (void)savePressed {
[selfdismissViewControllerAnimated:YES completion:nil];
self.city.notes = self.notesField.text;
USING A UIBARBUTTONITEM INSTEAD OF A UI
CityViewController.m
7/30/2019 Operation Models Slides
95/147
}
returnself;
} Check the Apple docs for all of the UIBarButtonSyste
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)ni
self = [superinitWithNibName:nibNameOrNil bundle:nibBundleOrNil
if(self) {
self.title = @"City"; self.tabBarItem.image = [UIImageimageNamed:@"tab_icon_city"
self.navigationItem.rightBarButtonItem = editButton;
UIBarButtonItem *editButton = [[UIBarButtonItemalloc]
initWithBarButtonSystemItem:UIBarButtonSystemI
target:self
action:@selector(editPres
OPENING EDITNOTEVIEWCONT
WITH AS A MODAL VIEW
7/30/2019 Operation Models Slides
96/147
PLANET HIG STRUCTURE SO FARAppDelegate
7/30/2019 Operation Models Slides
97/147
CityViewContr
EditNoteView
PlaceTableViewController
PlaceViewController
InterestingPlacesTableViewController
7/30/2019 Operation Models Slides
98/147
LEVEL 5
WHAT HAPPENS WHEN PLANECLOSED?
7/30/2019 Operation Models Slides
99/147
AWW COME ON - It TOOK
FOREVER TO MAKE THAT
SAVING MODEL DATA USING THE NSCODING PR
7/30/2019 Operation Models Slides
100/147
NSCoding all
easily store a
retrieve our NSString NSArray
Packaged Model Data
NSDictionary NSNumber
NSCoding
File
NSCODING IS LIKE A PACKING BOX
NSKeyedArchiver/Unarchiver
7/30/2019 Operation Models Slides
101/147
NSCoding
NSCoding is thepacking box that
contains your data
NSKeyedArchiver
+
Unarchiver
F
(
is the delivery person
The
the
City
City.h
@interface City : NSObject
ADOPTING THE NSCODING PROTOCOL
7/30/2019 Operation Models Slides
102/147
#import"City.h"
@end
City.m
- (id)init ...
@interface City:NSObject
- (id)initWithJSON ...
- (City*)initWithCoder:(NSCoder *)aDecoder {
}
- (void)encodeWithCoder:(NSCoder *)anEncoder {
}
initWithCoder
returnan instModel
must now impleinitWithCoder
encodeWithCod
IMPLEMENTING ENCODEWITHCODER:
City m
encodeWithCoder:formats data so it can be arc
7/30/2019 Operation Models Slides
103/147
City.m
Use @property namesas key names
@"name"@"state"
@"population"
@"notes"];
]
];];
Model properties
[anEncoder encodeObject:[anEncoder encodeObject:
[anEncoder encodeObject:
[anEncoder encodeObject:
self.nameself.state
self.population
self.notes
forKey:forKey:
forKey:
forKey:
- (void)encodeWithCoder:(NSCoder *)anEncoder {
}
IMPLEMENTING INITWITHCODER:
City.m
initWithCoder:unpacks data into a new object
7/30/2019 Operation Models Slides
104/147
y
- (City*)initWithCoder:(NSCoder *)aDecoder {
self = [super init];if(self) {
}
return self;
}
@"name"
@"state"
@"populati
@"notes"];
];
];
Use @property naas key names
Model properties
= [aDecoderdecodeObjectForKey:
= [aDecoder decodeObjectForKey:
= [aDecoder decodeObjectForKey:
= [aDecoder decodeObjectForKey:
self.name
self.state
self.population
self.notes
USE THE NSKEYED METHODS TO WORK WITH NinitWithCoder:andencodeWithCoder:dont get ca
7/30/2019 Operation Models Slides
105/147
Unarchive a Model with initWithCoder
City *city = [NSKeyedUnarchiverunarchiveObjectWithFile:ARCHIVE_P
Archive a Model with encodeWithCoder
City *city = [[Cityalloc] initWithJSON];
[NSKeyedArchiverarchiveRootObject:city toFile:ARCHIVE_PATH];
both need a patharchive file (war
IOS APP FOLDER HIERARCHY
d
7/30/2019 Operation Models Slides
106/147
APP App.bundle
DocumentsLibrary
tmp
Caches
Preferences
good place to saveModel data
read-only
PROGRAMMATICALLY ACCESSING THE DOCUMENTS
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDir
7/30/2019 Operation Models Slides
107/147
Give your archives a meaningful na
Unarchive a Model
Archive a Model
City *city = [[Cityalloc] initWithJSON];
archivePath];
archivePat
[docsDir stringByAppendingPathComponent:@"NSString *archivePath =
[NSKeyedArchiverarchiveRootObject:city toFile:
City *city = [NSKeyedUnarchiverunarchiveObjectWithFile:
NSUserDomainMY
NSString *docsDir = [paths objectAtIndex:0];
CREATING A CLASS METHOD TO FIND THE ARCHI
+ (NSString *)getPathToArchive {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumen
Dont forget to also declare this meClass method
7/30/2019 Operation Models Slides
108/147
Unarchive a Model
Archive a Model
[CitygetP
[CitygetPathToArch
City *city = [NSKeyedUnarchiverunarchiveObjectWithFile:
City *city = [[Cityalloc] initWithJSON];
[NSKeyedArchiverarchiveRootObject:city toFile:
}
[docsDir stringByAppendingPathComponent:@"city.model"];return
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumenNSUserDom
NSString *docsDir = [paths objectAtIndex:0];
CLASS METHODS TO SAVE AND RETRIEVE A MO
+ (NSString *)getPathToArchive {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumen
7/30/2019 Operation Models Slides
109/147
Just call these methods to save/retrieve the archive
+ (void)saveCity(City *)aCity {
}
+ (City *)getCity {
}
[NSKeyedArchiverarchiveRootObject:aCity toFile:
return [NSKeyedUnarchiverunarchiveObjectWithFile:
}
[docsDir stringByAppendingPathComponent:@"city.model"];return
City.m Class methods
[CitygetPat
[CitygetPathT
NSString *docsDir = [paths objectAtIndex:0];
NSUserDomNSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumen
WHERE AND WHEN TO ARCHIVE A MODEL OBJAppDelegate During Instantiatio
7/30/2019 Operation Models Slides
110/147
CityViewContr
EditNoteView
PlaceTableViewController
PlaceViewController
InterestingPlacesTableViewController
WHERE AND WHEN TO ARCHIVE A MODEL OBJ
City.mDuring Instantiatio
7/30/2019 Operation Models Slides
111/147
- (id)initWithJSON {
self = [superinit];
if(self) {
... // AFNetworking success block
self.name = JSON[@"name"];
self.state = JSON[@"state"];
self.population = JSON[@"population"];
[CitysaveCity:self];
}
returnself;
}
WHERE AND WHEN TO ARCHIVE A MODEL OBJAppDelegate After editing
7/30/2019 Operation Models Slides
112/147
CityViewContr
EditNoteView
PlaceTableViewController
PlaceViewController
InterestingPlacesTableViewController
textFieldShouldReturn:or savePressed:
WHERE AND WHEN TO ARCHIVE A MODEL OBJ
EditNoteViewController.m
After editing
7/30/2019 Operation Models Slides
113/147
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
}
returnYES;
self.city.notes = self.notesField.text;
[textFieldresignFirstResponder];
[CitysaveCity:self.city];
WHERE AND WHEN TO ARCHIVE A MODEL OBJ
When the app close
7/30/2019 Operation Models Slides
114/147
Wait, code runs even when
the app Closes?
UIAPPLICATIONDELEGATE PROTOCOL METHODAppDelegate.h
@interface AppDelegate : UIResponder
7/30/2019 Operation Models Slides
115/147
@interface AppDelegate:UIResponder
- (BOOL)application:(UIApplication *)applicationwillFinishLaunchingWithOptions:(NSDictionary *)options
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)options
- (void)applicationDidBecomeActive:(UIApplication *)application- (void)applicationWillResignActive:(UIApplication *)application
- (void)applicationDidEnterBackground:(UIApplication *)application
- (void)applicationWillEnterForeground:(UIApplication *)applicatio
APPLICATION LIFECYCLEapplication:willFinishLaunchingWithOpUser taps app
icon for the
7/30/2019 Operation Models Slides
116/147
applicationDidBecomeActive:
application:didFinishLaunchingWithOpt
applicationWillResignActive:
applicationDidEnterBackground:
applicationWillEnterForeground:
first time
app visuals appear
app interrupted- call comes in- home button tapped
normal usage
PERFORMING OPERATIONS IN THE APPDELEGAAppDelegate.m
@implementation AppDelegate
7/30/2019 Operation Models Slides
117/147
@ p e e a o pp e ega e
- (void)applicationDidEnterBackground:(UIApplication *)applicatio
- (void)applicationWillEnterForeground:(UIApplication *)applicati
}
}
// archive Model
// unarchive Model
Problem: The City Model object is in
CityViewController, not AppDelegate
APP DELEGATE NOTIFICATIONS
UIApplicationDidEnterBackgroundNAppDelegate
7/30/2019 Operation Models Slides
118/147
CityViewContr
EditNoteView
PlaceTableViewController
PlaceViewController
InterestingPlacesTableViewController
LISTENING FOR THE APPLICATION CLOSINGCityViewController.m
- (void)viewDidLoad {
7/30/2019 Operation Models Slides
119/147
[[NSNotificationCenterdefaultCenter]
addObserver:self
selector:@selector(entering
- (void)entering
Dont forget to re-creat
Model when the app open
Backgroundname:UIApplicationDidEnterBackgroundNotification
object:nil];
}
)
Background {
[CitysaveCity:self.city];
}
LISTENING FOR THE APPLICATION OPENINGCityViewController.m
- (void)viewDidLoad {
7/30/2019 Operation Models Slides
120/147
[[NSNotificationCenterdefaultCenter]
addObserver:self
selector:@selector(entering
- (void)entering
Foreground)name:UIApplicationWillEnterForegroundNotification
object:nil];
}
Foreground {
self.city = [City getCity];
}
WHERE AND WHEN TO UNARCHIVE A MODEL O
In Views that might need a Mo
but dont get a copy of it passe
7/30/2019 Operation Models Slides
121/147
PlaceTableViewController
PlaceViewController
CityViewContro
EditNoteViewCo
The City model isnt passed,so get it from the archive
CitPlace
WHERE AND WHEN TO UNARCHIVE A MODEL OPlaceTableViewController.h
#import"City.h"
7/30/2019 Operation Models Slides
122/147
@property (strong, nonatomic)City *city;
PlaceTableViewController.m
- (void)viewWillAppear:(BOOL)animated {
self.city = [City getCity];
}
PLANET HIG SAVING DATA
7/30/2019 Operation Models Slides
123/147
7/30/2019 Operation Models Slides
124/147
LEVEL 6
PLANET HIG - INTERESTINGPLACESTABLEVIEWCON
AppDelegate
7/30/2019 Operation Models Slides
125/147
CityViewContr
EditNoteView
PlaceTableViewController
PlaceViewController
InterestingPlacesTableViewController
Lets get this tableview working
ADDING AN INTERESTINGPLACES NSARRAY @PR
#import
City.h
7/30/2019 Operation Models Slides
126/147
@end
@interface City : NSObject
@property (strong, nonatomic)NSString*name;
- (id)initWithJSON;
@property (strong, nonatomic)NSString*state;
@property (strong, nonatomic)NSNumber*population;
@property (strong, nonatomic)NSString*notes;
@property (strong, nonatomic)NSArray* ;interestingPlaces
SETTING THE INITIAL VALUE OF INTERESTINGP
City.m
@implementation City No default interesting plac
7/30/2019 Operation Models Slides
127/147
@end
- (id)init { self = [self initWithJSON];
}
- (id)initWithJSON { self = [selfinit];
if(self) { ...
...}
return self;}
= nil;self.interestingPlaces
GETTING THE CITY MODEL INTO PLACEVIEWCON
PlaceViewController.h
#import
7/30/2019 Operation Models Slides
128/147
@property (strong, nonatomic) City *city;
#import
#import"City.h"
@end
@interface PlaceViewController : UIViewController
@property (strong, nonatomic) Place *place;
#import"Place.h"
-(void) (id)sender;makeThisPlaceInteresting:
ADDING A UIBUTTON TO MARK A PLACE AS INTE
PlaceViewController.m
-(void)viewWillAppear:(BOOL)animated{
7/30/2019 Operation Models Slides
129/147
...
}
UIButton *interestingButton = [UIButtonbuttonWithType:UIButtonTyp
interestingButton.frame = CGRectMake(60,100,200,44);
[interestingButton setTitle:@"Mark as Interesting"forState:UICont
[self.viewaddSubview:interestingButton];
[interestingButton addTarget:self
forControlEvents:UIControlEventTouchUpInside];
action:@selector( )makeThisPlaceInteresting:
self.city = [CitygetCity];
IMPLEMENTING MAKETHISPLACEINTERESTING
NSMutableArray *tempArray = [[NSMutableArray alloc]
-(void) (id)sender{
PlaceViewController.m
makeThisPlaceInteresting:
7/30/2019 Operation Models Slides
130/147
}
[CitysaveCity:self.city];
NSMutableArray *tempArray = [[NSMutableArrayalloc]
initWithArray:self.city.interest
[tempArray addObject:self.place];
self.city.interestingPlaces = [[NSArrayalloc] initWithArray:tem
PLACEVIEWCONTROLLER DEM
7/30/2019 Operation Models Slides
131/147
INTERESTINGPLACESTABLEVIEWCONTROLLER UITABLEVIEW
InterestingPlacesTableViewController.m
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
7/30/2019 Operation Models Slides
132/147
returnself.city.interestingPlaces.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (void) tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
UITABLEVIEW CELLFORROWATINDEXPATH: FROM
InterestingPlacesTableViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
7/30/2019 Operation Models Slides
133/147
UITableViewCell *cell = [tableView dequeueReusableCellWithIdenti
if(cell == nil) {cell = [[UITableViewCellalloc] initWithStyle:UITableViewCel
reuseIdentifier:@"pCell"];}
cell.textLabel.text = [self.city.interestingPlaces[indexPath.row
return cell;
}
PUSH A PLACE MODEL INSTANCE WHEN A CELL IS
InterestingPlacesTableViewController.m
- (void) tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
7/30/2019 Operation Models Slides
134/147
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
PlaceViewController *placeVC = [PlaceViewController alloc] init]
placeVC.place = self.city.interestingPlaces[indexPath.row];
[self.navigationControllerpushViewController:placeVC animated:Y
InterestingPlacesTableViewController Cell PlaceVPlace Model instance passed when cell is tapped
INTERESTINGPLACES
TABLEVIEWCONTROLLER DEMO
7/30/2019 Operation Models Slides
135/147
REMOVE THE BUTTON AFTER ADDING A PLACE
PlaceViewController.m
- (void)makeThisPlaceInteresting:(id)sender{
sender is the button that called the
7/30/2019 Operation Models Slides
136/147
}
self.city = [CitygetCity];
NSMutableArray *tempArray = [[NSMutableArrayalloc]initWithArray:self.city.intere
[tempArray addObject:[[Placealloc] initWithName:self.placeName
description:self.placeDesc
self.city.interestingPlaces = [[NSArrayalloc] initWithArray:te
[CitysaveCity:self.city];
[sender removeFromSuperview];
SHOW AN ALERT VIEW WHEN MAKING A PLACE INT
PlaceViewController.m
- (void)makeThisPlaceInteresting:(id)sender{
7/30/2019 Operation Models Slides
137/147
}
[sender removeFromSuperview];
...
UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"Place favorited"
message:@"This Place is now in your fav
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
UIALERTVIEW ELEMENTS
UIAlertView *alert = [[UIAlertViewalloc]
initWithTitle:@"Place favorited"
message:@"This Place is now in your favorites
7/30/2019 Operation Models Slides
138/147
title messag
cancelButtonTitle
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
PROBLEM: THE BUTTON COM
7/30/2019 Operation Models Slides
139/147
DONT SHOW THE BUTTON IF THE PLACE IS ALREADY INT
PlaceViewController.m
-(void)viewWillAppear:(BOOL)animated{
if(![self.city.interestingPlacescontainsObject:self.place]) {
7/30/2019 Operation Models Slides
140/147
}
// show the button because this Place isn't interesting ye
} else { // don't show the button because this Place is already int
}
Thats a bummer, man!
DONT SHOW THE BUTTON IF THE PLACE IS ALREADY INT
PlaceViewController.m
BOOLplaceAlreadyInteresting = NO;
-(void)viewWillAppear:(BOOL)animated{
7/30/2019 Operation Models Slides
141/147
for (Place *p in self.city.interestingPlaces) {
}
if([p.nameisEqualToString:self.place.name]) {placeAlreadyInteresting = YES;
}
}
// show the button because this Place isn't interesting ye
} else {
// don't show the button because this Place is already int
}
if( ) {!placeAlreadyInteresting
ACCESSING UITABBARITEMS
tabBarController.tabBa
7/30/2019 Operation Models Slides
142/147
badgeitems[0] items[1]
self.tabBarController.tabBar.ite
the Interesting Places tabBarItem
SET THE UITABBARITEM BADGE VALUE
UITabBarItem Property
7/30/2019 Operation Models Slides
143/147
Convert the count integer to an NSString
[self.tabBarController.tabBar.items[1]
setBadgeValue:[NSStringstringWithFormat:@
self.city.interestingPlaces
WHERE AND WHEN TO UPDATE SETBADGEVAL
AppDelegateUpdate when the app firs
7/30/2019 Operation Models Slides
144/147
CityViewContr
EditNoteView
PlaceTableViewController
PlaceViewController
InterestingPlacesTableViewController
Update inmakeThisPlaceInteresting:
UPDATE THE BADGE WHEN THE APP LAUNCHES
AppDelegate.h
@interface AppDelegate:UIResponder
#import"City.h"
7/30/2019 Operation Models Slides
145/147
AppDelegate.m
- (BOOL) application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
}
...
City *city = [CitygetCity];
[tabBarController.tabBar.items[1]
setBadgeValue:[NSStringstringWithFormat:@city.interestingPlaces.coun
if(city) {
}
UPDATE THE BADGE WHEN A PLACE IS MARKED INTERES
PlaceViewController.m
- (void)makeThisPlaceInteresting:(id)sender{
...UIAlertView *alert = [[UIAlertViewalloc]
7/30/2019 Operation Models Slides
146/147
}
[sender removeFromSuperview];
initWithTitle:@"Place favorited"
message:@"This Place is now in your favor
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[self.tabBarController.tabBar.items[1]
setBadgeValue:[NSStringstringWithFormself.city.interestingPl
PLANET HIG
7/30/2019 Operation Models Slides
147/147
This thing just keeps
getting better!