iOS app case study

Post on 10-May-2015

3.060 views 0 download

Tags:

description

The slides from a lecture I gave at RMIT doing a case study of a simple property search application.

Transcript of iOS app case study

iPhone App Case Study

Stewart Gleadowsgleadow@thoughtworks.com@stewgleadow

Friday, 16 September 11

Why iPhone development?

Friday, 16 September 11

YOW Conference

• Workshops November 28-30

• Conference December 1-2

• http://www.yowconference.com.au/

• lisa@yowconference.com

Friday, 16 September 11

Common featuresin iPhone apps

Friday, 16 September 11

Outline

1. Basic table views

2. Custom table views

3. Dynamic content

4. Master/detail navigation

5. Make it awesome

Friday, 16 September 11

Games

Friday, 16 September 11

Camera control

Friday, 16 September 11

Basic tables

Friday, 16 September 11

Advanced tables

Friday, 16 September 11

Forms

Friday, 16 September 11

Scroll views

Friday, 16 September 11

Maps

Friday, 16 September 11

Location awareness

Friday, 16 September 11

Master/detail navigation

Friday, 16 September 11

Master/detail navigation

Friday, 16 September 11

Consuming and presenting information

from the web

Friday, 16 September 11

Build up your toolbox

Friday, 16 September 11

Build up your toolbox

http://cocoawithlove.com/2011/06/process-of-writing-ios-application.html

Friday, 16 September 11

Build up your toolbox

http://cocoawithlove.com/2011/06/process-of-writing-ios-application.html

Friday, 16 September 11

1. Basic table view

Friday, 16 September 11

PropertyAn Objective C domain model class

Friday, 16 September 11

PropertyAn Objective C domain model class

@interface Property : NSObject

@property (nonatomic, copy) NSString *address;@property (nonatomic, copy) NSString *suburb;@property (nonatomic, copy) NSString *postode;

@property (nonatomic, retain) UIImage *photo;@property (nonatomic, copy) NSString *summary;

- (NSString *)location;

@end

Friday, 16 September 11

PropertyAn Objective C domain model class

@interface Property : NSObject

@property (nonatomic, copy) NSString *address;@property (nonatomic, copy) NSString *suburb;@property (nonatomic, copy) NSString *postode;

@property (nonatomic, retain) UIImage *photo;@property (nonatomic, copy) NSString *summary;

- (NSString *)location;

@end

Put logic in your model classes

Friday, 16 September 11

PropertyMake your objects easy to create and configure

Friday, 16 September 11

PropertyMake your objects easy to create and configure

+ (Property *)propertyWithAddess:(NSString *)anAddress suburb:(NSString *)aSuburb postcode:(NSString *)aPostcode photo:(NSString *)photoName summary:(NSString *)aSummary;{ Property *property = [[[Property alloc] init] autorelease]; property.address = anAddress; property.suburb = aSuburb; property.postode = aPostcode; property.photo = [UIImage imageNamed:photoName]; property.summary = aSummary; return property;}

Friday, 16 September 11

UITableView

UIViewController

Friday, 16 September 11

UITableView

UIViewController

UITableViewDataSource

UITableViewDelegate

UITableViewCell

Friday, 16 September 11

UITableView

Friday, 16 September 11

UITableView *table;table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];

Creating your UITableView

UITableView

Friday, 16 September 11

UITableView *table;table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];

table.delegate = self;table.dataSource = self;

Creating your UITableView

Setting up your delegates

UITableView

Friday, 16 September 11

UITableView *table;table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];

[self.view addSubview:table];

table.delegate = self;table.dataSource = self;

Creating your UITableView

Setting up your delegates

Adding the table to the view

UITableView

Friday, 16 September 11

UITableView

Friday, 16 September 11

UITableView

Friday, 16 September 11

UITableViewCell

Friday, 16 September 11

UITableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;

Creating a table cell

Friday, 16 September 11

UITableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;

Creating a table cell

[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"RMITCellIdentifier"];

Friday, 16 September 11

UITableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;

Creating a table cell

[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"RMITCellIdentifier"];

Reuse is important

Friday, 16 September 11

UITableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;

Creating a table cell

[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"RMITCellIdentifier"];

Reuse is important

Configuring the cellcell.textLabel.text = @"title string";cell.detailTextLabel.text = @"subtitle string";

Friday, 16 September 11

UITableViewDataSource

Friday, 16 September 11

UITableViewDataSourceHow many sections do I have?

Friday, 16 September 11

UITableViewDataSourceHow many sections do I have?

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

Friday, 16 September 11

UITableViewDataSourceHow many sections do I have?

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

How many rows are in each section?

Friday, 16 September 11

UITableViewDataSourceHow many sections do I have?

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

How many rows are in each section?- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

Friday, 16 September 11

UITableViewDataSourceHow many sections do I have?

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

How many rows are in each section?- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

What is the cell for a given row/section?

Friday, 16 September 11

UITableViewDataSource

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

How many sections do I have?- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

How many rows are in each section?- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

What is the cell for a given row/section?

Friday, 16 September 11

Demo 1:Basic table view

Friday, 16 September 11

2. Custom table view

Friday, 16 September 11

UITableViewCell

textLabelimageView

detailTextLabel

Friday, 16 September 11

UITableViewCell

textLabelimageView

detailTextLabel

• backgroundView

• selectedBackgroundView

• contentView

Plus:

Friday, 16 September 11

Customising Cellsif (cell == nil){ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier] autorelease];

self.textLabel.backgroundColor = [UIColor clearColor]; self.textLabel.font = [UIFont boldSystemFontOfSize:14]; self.textLabel.shadowOffset = CGSizeMake(0, 1);

// And a whole lot more}

Friday, 16 September 11

Customising Cellsif (cell == nil){ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier] autorelease];

self.textLabel.backgroundColor = [UIColor clearColor]; self.textLabel.font = [UIFont boldSystemFontOfSize:14]; self.textLabel.shadowOffset = CGSizeMake(0, 1);

// And a whole lot more}

Friday, 16 September 11

Customising Cellsif (cell == nil){ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier] autorelease];

self.textLabel.backgroundColor = [UIColor clearColor]; self.textLabel.font = [UIFont boldSystemFontOfSize:14]; self.textLabel.shadowOffset = CGSizeMake(0, 1);

// And a whole lot more}

Refactor into our own styled cell class

Friday, 16 September 11

PropertyCellA subclass of UITableViewcell

Friday, 16 September 11

PropertyCellA subclass of UITableViewcell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { self.textLabel.textColor = [UIColor darkGrayColor]; self.textLabel.backgroundColor = [UIColor clearColor]; // More cell styling code goes here } return self;}

Friday, 16 September 11

Demo 2:Custom table view

Friday, 16 September 11

3. Dynamic content

Friday, 16 September 11

Backend server

• Hosted on Heroku

• http://rmit-property-search.heroku.com/search

• Written in Ruby

• Uses the Sinatra framework

Friday, 16 September 11

Server code

Friday, 16 September 11

Server code

require 'rubygems'require 'bundler'require 'erb'Bundler.require

get '/search' do @search = params[:q] erb :propertiesend

Friday, 16 September 11

Server code

require 'rubygems'require 'bundler'require 'erb'Bundler.require

get '/search' do @search = params[:q] erb :propertiesend

templateJSON file

Friday, 16 September 11

Example JSON

Friday, 16 September 11

Example JSON{ "title" : "", "properties" : [ { "address" : "60-74 Buckingham Drive", "suburb" : "Heidelberg", "postcode" : "3084", "photo" : "photo1.jpg", "summary" : "Banyule House, 1839" }, { "address" : "3 Macedon Street", "suburb" : "Sunbury", "postcode" : "3429" , "photo" : "photo10.jpg", "summary" : "Rupertswood" },

... ]}

Friday, 16 September 11

Networking

Friday, 16 September 11

Don’t reinvent the wheel

Networking

Friday, 16 September 11

LRResty

Friday, 16 September 11

Performing a GET request

LRResty

- (IBAction)search{ [[LRResty client] get:@"http://rmit-property-search.heroku.com/search" delegate:self];}

Friday, 16 September 11

Performing a GET request

- (void)restClient:(LRRestyClient *)client receivedResponse:(LRRestyResponse *)response;{ NSData *data = [response responseData]; // convert data to property objects}

LRResty

Receiving the delegate callback

- (IBAction)search{ [[LRResty client] get:@"http://rmit-property-search.heroku.com/search" delegate:self];}

Friday, 16 September 11

Parsing data

Friday, 16 September 11

Don’t reinvent the wheel

Parsing data

Friday, 16 September 11

Don’t reinvent the wheel

• JSONKit

• json framework

• YAJL

Parsing data

Friday, 16 September 11

Don’t reinvent the wheel

• JSONKit

• json framework

• YAJL

Parsing data

Friday, 16 September 11

YAJL

Friday, 16 September 11

Converting NSString or NSData to JSON

YAJL

- (id)yajl_JSON;

Friday, 16 September 11

Converting NSString or NSData to JSON

YAJL

- (id)yajl_JSON;

NSDictionary *jsonDict = [data yajl_JSON];NSArray *propertiesArray = [jsonDict valueForKey:@"properties"];

NSMutableArray *newProperties = [NSMutableArray array];

for (NSDictionary *dict in propertiesArray){ Property *property = [Property propertyWithDictionary:dict]; [newProperties addObject:property];}

Extracting property data

Friday, 16 September 11

Converting NSString or NSData to JSON

YAJL

- (id)yajl_JSON;

NSDictionary *jsonDict = [data yajl_JSON];NSArray *propertiesArray = [jsonDict valueForKey:@"properties"];

NSMutableArray *newProperties = [NSMutableArray array];

for (NSDictionary *dict in propertiesArray){ Property *property = [Property propertyWithDictionary:dict]; [newProperties addObject:property];}

Extracting property data

Friday, 16 September 11

NSDictionary -> Property

Friday, 16 September 11

Pull the values you want out of the dictionary

NSDictionary -> Property

+ (Property *)propertyWithDictionary:(NSDictionary *)dict{ return [Property propertyWithAddess:[dict valueForKey:@"address"] suburb:[dict valueForKey:@"suburb"] postcode:[dict valueForKey:@"postcode"] photo:[dict valueForKey:@"photo"] summary:[dict valueForKey:@"summary"]];}

Friday, 16 September 11

Demo 3:Dynamic content

Friday, 16 September 11

4. Master/detailnavigation

Friday, 16 September 11

DetailViewController

Friday, 16 September 11

Creating the new view controller with a property

Friday, 16 September 11

Creating the new view controller with a property

- (id)initWithProperty:(Property *)aProperty{ if ((self = [super initWithNibName:@"DetailViewController" bundle:nil])) { self.property = aProperty; self.title = @"Property"; } return self;}

Friday, 16 September 11

Updating content in the DetailViewController

Friday, 16 September 11

Updating content in the DetailViewController

- (void)viewDidLoad;{ [super viewDidLoad]; self.address.text = self.property.address; self.location.text = self.property.location; self.photo.image = self.property.photo; self.summary.text = self.property.summary;}

Friday, 16 September 11

UITableViewDelegate- (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath;

Friday, 16 September 11

UITableViewDelegate- (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath;

• pull out the Property object for selected row

• create a new DetailViewController with that Property

• push the new controller onto the navigation stack

Friday, 16 September 11

Demo 4:Master / Detail

Friday, 16 September 11

5. Make it awesome

Friday, 16 September 11

What’s missing?

Friday, 16 September 11

What’s missing?

• Can’t dismiss the keyboard

Friday, 16 September 11

What’s missing?

• Can’t dismiss the keyboard

• Search does not actually search

Friday, 16 September 11

What’s missing?

• Can’t dismiss the keyboard

• Search does not actually search

• No progress indicator while loading

Friday, 16 September 11

What’s missing?

• Can’t dismiss the keyboard

• Search does not actually search

• No progress indicator while loading

• People like pull-to-refresh like Facebook

Friday, 16 September 11

Demo 5:Making it awesome

Friday, 16 September 11

The finished product

Friday, 16 September 11

The finished product

Friday, 16 September 11

Master/detail navigation

Friday, 16 September 11

Summary

1. Basic table views

2. Custom table views

3. Dynamic content

4. Master/detail navigation

5. Make it awesome

Friday, 16 September 11

iPhone App Case Study

Stewart Gleadowgsgleadow@thoughtworks.com

Friday, 16 September 11

Appendix

Friday, 16 September 11

Links

• https://github.com/lukeredpath/LRResty

• http://gabriel.github.com/yajl-objc/

• https://github.com/jdg/MBProgressHUD

• https://github.com/chpwn/PullToRefreshView

• http://www.heroku.com/

• http://www.sinatrarb.com/

Friday, 16 September 11

Linking static libraries and frameworks

Friday, 16 September 11

Other linker flags: -all_load -ObjC

Linking static libraries and frameworks

Friday, 16 September 11