iOS app case study

3,673 views

Published on

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

Published in: Technology, Business
0 Comments
11 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,673
On SlideShare
0
From Embeds
0
Number of Embeds
1,283
Actions
Shares
0
Downloads
75
Comments
0
Likes
11
Embeds 0
No embeds

No notes for slide

iOS app case study

  1. 1. iPhone App Case Study Stewart Gleadow sgleadow@thoughtworks.com @stewgleadowFriday, 16 September 11
  2. 2. Why iPhone development?Friday, 16 September 11
  3. 3. YOW Conference • Workshops November 28-30 • Conference December 1-2 • http://www.yowconference.com.au/ • lisa@yowconference.comFriday, 16 September 11
  4. 4. Common features in iPhone appsFriday, 16 September 11
  5. 5. Outline 1. Basic table views 2. Custom table views 3. Dynamic content 4. Master/detail navigation 5. Make it awesomeFriday, 16 September 11
  6. 6. GamesFriday, 16 September 11
  7. 7. Camera controlFriday, 16 September 11
  8. 8. Basic tablesFriday, 16 September 11
  9. 9. Advanced tablesFriday, 16 September 11
  10. 10. FormsFriday, 16 September 11
  11. 11. Scroll viewsFriday, 16 September 11
  12. 12. MapsFriday, 16 September 11
  13. 13. Location awarenessFriday, 16 September 11
  14. 14. Master/detail navigationFriday, 16 September 11
  15. 15. Master/detail navigationFriday, 16 September 11
  16. 16. Consuming and presenting information from the webFriday, 16 September 11
  17. 17. Build up your toolboxFriday, 16 September 11
  18. 18. Build up your toolbox http://cocoawithlove.com/2011/06/process-of-writing-ios-application.htmlFriday, 16 September 11
  19. 19. Build up your toolbox http://cocoawithlove.com/2011/06/process-of-writing-ios-application.htmlFriday, 16 September 11
  20. 20. 1. Basic table viewFriday, 16 September 11
  21. 21. Property An Objective C domain model classFriday, 16 September 11
  22. 22. Property An 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; @endFriday, 16 September 11
  23. 23. Property An 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 classesFriday, 16 September 11
  24. 24. Property Make your objects easy to create and configureFriday, 16 September 11
  25. 25. Property Make 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
  26. 26. UIViewController UITableViewFriday, 16 September 11
  27. 27. UIViewController UITableView UITableViewDataSource UITableViewDelegate UITableViewCellFriday, 16 September 11
  28. 28. UITableViewFriday, 16 September 11
  29. 29. UITableView Creating your UITableView UITableView *table; table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];Friday, 16 September 11
  30. 30. UITableView Creating your UITableView UITableView *table; table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; Setting up your delegates table.delegate = self; table.dataSource = self;Friday, 16 September 11
  31. 31. UITableView Creating your UITableView UITableView *table; table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; Setting up your delegates table.delegate = self; table.dataSource = self; Adding the table to the view [self.view addSubview:table];Friday, 16 September 11
  32. 32. UITableViewFriday, 16 September 11
  33. 33. UITableViewFriday, 16 September 11
  34. 34. UITableViewCellFriday, 16 September 11
  35. 35. UITableViewCell Creating a table cell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;Friday, 16 September 11
  36. 36. UITableViewCell Creating a table cell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier; [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"RMITCellIdentifier"];Friday, 16 September 11
  37. 37. UITableViewCell Creating a table cell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier; [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"RMITCellIdentifier"]; Reuse is importantFriday, 16 September 11
  38. 38. UITableViewCell Creating a table cell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier; [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"RMITCellIdentifier"]; Reuse is important Configuring the cell cell.textLabel.text = @"title string"; cell.detailTextLabel.text = @"subtitle string";Friday, 16 September 11
  39. 39. UITableViewDataSourceFriday, 16 September 11
  40. 40. UITableViewDataSource How many sections do I have?Friday, 16 September 11
  41. 41. UITableViewDataSource How many sections do I have? - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;Friday, 16 September 11
  42. 42. UITableViewDataSource How many sections do I have? - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; How many rows are in each section?Friday, 16 September 11
  43. 43. UITableViewDataSource How 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
  44. 44. UITableViewDataSource 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
  45. 45. UITableViewDataSource 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? - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;Friday, 16 September 11
  46. 46. Demo 1: Basic table viewFriday, 16 September 11
  47. 47. 2. Custom table viewFriday, 16 September 11
  48. 48. UITableViewCell textLabel imageView detailTextLabelFriday, 16 September 11
  49. 49. UITableViewCell textLabel imageView detailTextLabel Plus: • backgroundView • selectedBackgroundView • contentViewFriday, 16 September 11
  50. 50. Customising Cells if (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
  51. 51. Customising Cells if (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
  52. 52. Customising Cells if (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 classFriday, 16 September 11
  53. 53. PropertyCell A subclass of UITableViewcellFriday, 16 September 11
  54. 54. PropertyCell A 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
  55. 55. Demo 2: Custom table viewFriday, 16 September 11
  56. 56. 3. Dynamic contentFriday, 16 September 11
  57. 57. Backend server • Hosted on Heroku • http://rmit-property-search.heroku.com/search • Written in Ruby • Uses the Sinatra frameworkFriday, 16 September 11
  58. 58. Server codeFriday, 16 September 11
  59. 59. Server code require rubygems require bundler require erb Bundler.require get /search do @search = params[:q] erb :properties endFriday, 16 September 11
  60. 60. Server code require rubygems require bundler require erb Bundler.require get /search do @search = params[:q] template erb :properties end JSON fileFriday, 16 September 11
  61. 61. Example JSONFriday, 16 September 11
  62. 62. 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
  63. 63. NetworkingFriday, 16 September 11
  64. 64. Networking Don’t reinvent the wheelFriday, 16 September 11
  65. 65. Networking Don’t reinvent the wheel • NSURLConnection • ASIHttpRequest • LRResty • AFNetworking • RestKitFriday, 16 September 11
  66. 66. Networking Don’t reinvent the wheel • NSURLConnection • ASIHttpRequest • LRResty • AFNetworking • RestKitFriday, 16 September 11
  67. 67. LRRestyFriday, 16 September 11
  68. 68. LRResty Performing a GET request - (IBAction)search { [[LRResty client] get:@"http://rmit-property-search.heroku.com/search" delegate:self]; }Friday, 16 September 11
  69. 69. LRResty Performing a GET request - (IBAction)search { [[LRResty client] get:@"http://rmit-property-search.heroku.com/search" delegate:self]; } Receiving the delegate callback - (void)restClient:(LRRestyClient *)client receivedResponse:(LRRestyResponse *)response; { NSData *data = [response responseData]; // convert data to property objects }Friday, 16 September 11
  70. 70. Parsing dataFriday, 16 September 11
  71. 71. Parsing data Don’t reinvent the wheelFriday, 16 September 11
  72. 72. Parsing data Don’t reinvent the wheel • JSONKit • json framework • YAJLFriday, 16 September 11
  73. 73. Parsing data Don’t reinvent the wheel • JSONKit • json framework • YAJLFriday, 16 September 11
  74. 74. YAJLFriday, 16 September 11
  75. 75. YAJL Converting NSString or NSData to JSON - (id)yajl_JSON;Friday, 16 September 11
  76. 76. YAJL Converting NSString or NSData to JSON - (id)yajl_JSON; Extracting property data 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]; }Friday, 16 September 11
  77. 77. YAJL Converting NSString or NSData to JSON - (id)yajl_JSON; Extracting property data 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]; }Friday, 16 September 11
  78. 78. NSDictionary -> PropertyFriday, 16 September 11
  79. 79. NSDictionary -> Property Pull the values you want out of the dictionary+ (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
  80. 80. Demo 3: Dynamic contentFriday, 16 September 11
  81. 81. 4. Master/detail navigationFriday, 16 September 11
  82. 82. DetailViewControllerFriday, 16 September 11
  83. 83. Creating the new view controller with a propertyFriday, 16 September 11
  84. 84. 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
  85. 85. Updating content in the DetailViewControllerFriday, 16 September 11
  86. 86. 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
  87. 87. UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;Friday, 16 September 11
  88. 88. UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; • pull out the Property object for selected row • create a new DetailViewController with that Property • push the new controller onto the navigation stackFriday, 16 September 11
  89. 89. Demo 4: Master / DetailFriday, 16 September 11
  90. 90. 5. Make it awesomeFriday, 16 September 11
  91. 91. What’s missing?Friday, 16 September 11
  92. 92. What’s missing? • Can’t dismiss the keyboardFriday, 16 September 11
  93. 93. What’s missing? • Can’t dismiss the keyboard • Search does not actually searchFriday, 16 September 11
  94. 94. What’s missing? • Can’t dismiss the keyboard • Search does not actually search • No progress indicator while loadingFriday, 16 September 11
  95. 95. What’s missing? • Can’t dismiss the keyboard • Search does not actually search • No progress indicator while loading • People like pull-to-refresh like FacebookFriday, 16 September 11
  96. 96. Demo 5: Making it awesomeFriday, 16 September 11
  97. 97. The finished productFriday, 16 September 11
  98. 98. The finished productFriday, 16 September 11
  99. 99. Master/detail navigationFriday, 16 September 11
  100. 100. Summary 1. Basic table views 2. Custom table views 3. Dynamic content 4. Master/detail navigation 5. Make it awesomeFriday, 16 September 11
  101. 101. iPhone App Case Study Stewart Gleadow g sgleadow@thoughtworks.comFriday, 16 September 11
  102. 102. AppendixFriday, 16 September 11
  103. 103. 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
  104. 104. Linking static libraries and frameworksFriday, 16 September 11
  105. 105. Linking static libraries and frameworks Other linker flags: -all_load -ObjCFriday, 16 September 11

×