SlideShare a Scribd company logo
Luis Rei
LuisRei.com
me@luisrei.com
@lmrei
Developing
iOS
REST
Applications
• WHOAMI
• GLAZEDSOLUTIONS.COM
• HTML5 Mobile Apps - Friday 15h Main Stage
• It’s awesome: iPhone, iPad, iPod Touch
• Best Mobile App Dev Platform (by light years)
• Objective-C + Foundation + Cocoa
• Lots of potential users
• lots of potentially paying users
Why iOS
• Software architecture for distributed systems
• say web services/APIs
• Client-Server
• Works over HTTP & URI-based
• http://api.twitter.com/1/statuses/public_timeline.json
REST Quick Intro
• There’s always something you need in “the cloud”
• Data or processing power
• More true on mobile
• Universal: mobile, desktop, web clients
• It’s easy to implement server side ( at least the basic stuff)
• and everyone is doing it (twitter, github, amazon, google, ...)
• It’s easy to implement on the client
Why REST
REST/REST-Like APIs
iOS REST Recipe
Function Library I Use Currently iOS Boilerplate
HTTP Requests ASIHTTPRequest AFNetworking
JSON
SBJson
(AKA json-framework)
JSONkit
Image Caching
AFNetworking
(I previously used HJCache)
AFNetworking
Pull-To-Refresh
PullToRefreshTableViewController
by Leah Culver
EGOTableViewPullToRefresh
HUD
SVProgessHUD
(I previously used DSActivityView)
SVProgessHUD
• Am I connected to the internet?
• Wifi or Cellular?
Reachability
(SystemConfiguration framework)
NSString * const SRVR = @"api.example.com";
-(BOOL)reachable
{
    Reachability *r = [Reachability reachabilityWithHostName:SRVR];
    NetworkStatus internetStatus = [r currentReachabilityStatus];
    if(internetStatus == NotReachable) {
        return NO;
    }
    return YES;
}
NotReachable
ReachableViaWifi
ReachableViaWWAN
GET
- (void)makeGetRequest
{
NSURL *url = [NSURL URLWithString:@"http://api.example.com"];
ASIHTTPRequest *request =
[ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSError *error = [request error];
if (!error && [request responseStatusCode] == 200)
{
NSString *response = [request responseString];
//NSData *responseData = [request responseData];
}
Errors
else if(error)
NSLog(@"request error: %@",[error localizedDescription]);
else if([request responseStatusCode] != 200)
NSLog(@"server says: %@", [request responseString]);
}
•The app continues to execute
•UI continues to be responsive
•The request runs in the background
•Two (common) ways of doing it in iOS:
•Delegate
•Block
Asynchronous Requests
• The delegator object has a delegate property that
points to the delegate object
• A delegate acts when its delegator encounters a
certain event
• The delegate adopts a protocol
• We’ll need 2 methods: success & failure
Cocoa Delegate Pattern
Asynchronous GET
- (void)makeGetRequest
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
// DELEGATE METHODS:
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSString *responseString = [request responseString];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}
Cocoa Blocks
• Ad hoc function body as an expression
• Carry their code & the data they need
• ideal for callbacks
• We’ll need 2 blocks: success & failure
Building Blocks
- (void)makeGetRequest
{
NSURL *url = [NSURL URLWithString:@"http://api.example.com"];
__block ASIHTTPRequest *request =
[ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{
NSString *responseString = [request responseString];
}];
[request setFailedBlock:^{
NSError *error = [request error];
}];
[request startAsynchronous];
}
SVProgressHUD
#import "SVProgressHUD.h"
- (void)makeGetRequest
{
NSURL *url = [NSURL URLWithString:@"http://api.example.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[SVProgressHUD showWithStatus:@"Fetching data"];
[request startSynchronous];
if (![request error])
{
" [SVProgressHUD dismissWithSuccess:@"Fetch Successful"];
...
}
else {
" [SVProgressHUD dismissWithError:@"Fetch Failed"];
...
}
}
Where to Load Data
• viewDidLoad / viewWillAppear
• Make the asynchronous request
• Show HUD or other “loading” indicators
• LOADED = NO;
• Delegate
• LOADED = YES;
• Reload table
• Partial Load + Pagination
• Load more at the end of the table
PullToRefresh
Developing iOS REST Applications
#import "PullRefreshTableViewController.h"
@interface MyTableViewController : PullRefreshTableViewController
- (void)refresh
{
  [self performSelector:@selector(add) withObject:nil afterDelay:2.0];
}
- (void) add
{
...
[self stopLoading];
}
.m
.h
Background Loading
& Caching Images
#import "UIImageView+AFNetworking.h"
NSURL *imageURL = [NSURL URLWithString:@”http://example.com/picture.jpg”];
UIImageView *image = [[UIImageView alloc] init];
[image setImageWithURL:imageURL];
Updating My Profile Picture
•Modify an existing record
•Authenticate
•Upload a file
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setRequestMethod:@"PUT"]; //REST modify using PUT
[request setPostFormat:ASIMultipartFormDataPostFormat];
// authentication
[request setUsername:username];
[request setPassword:password];
[request setFile:jpgPath forKey:@"image"];
"
[request startSynchronous];
POST & DELETE
[request setRequestMethod:@"POST"];
[request setRequestMethod:@"DELETE"];
I JSON (because it’s not XML)
JSON OBJECTIVE-C/FOUNDATION
Object NSDictionary
Array NSArray
String NSString
Number NSNumber
Boolean NSNumber (0 or 1)
1. Download a JSON string (via an http request)
2.Convert it to native data structures (parsing)
3.Use the native data structures
Parsing
[request startSynchronous];
...
SBJsonParser *prsr = [[[SBJsonParser alloc] init] autorelease];
// object
NSDictionary *data = [prsr objectWithString:[request responseString]];
// or Array
NSArray *data = [parsr objectWithString:[request responseString]];
INCEPTION
[{[{}]}]
An array of
objects with an
array of objects
[
	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  "name":	
  "object1",
	
  	
  	
  	
  	
  	
  	
  	
  "sub":	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "name":	
  "subobject1"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  },
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "name":	
  "subobject2"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  },
	
  	
  	
  
]
or rather JCEPTION
NSArray *jArray = [prsr objectWithString:data];
NSDictionary *obj1 = [jArray objectAtIndex:0];
NSString *obj1Name = [obj1 objectForKey:@”name”];
NSArray *obj1SubArray = [obj1 objectForKey:@”sub”];
NSDictionary *subObj1 = [obj1SubArray objectAtIndex:0];
NSNumber *subObj1Val = [subObj1 objectForKey@”value”];
[
	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  "name":	
  "object1",
	
  	
  	
  	
  	
  	
  	
  	
  "sub":	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "name":	
  "subobject1"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  },
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "value":	
  1
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  },
]
...[[[prsr objectWithSring:data] objectAtIndex:0] objectForKey:@”sub]...
Developing iOS REST Applications

More Related Content

Developing iOS REST Applications

  • 2. • WHOAMI • GLAZEDSOLUTIONS.COM • HTML5 Mobile Apps - Friday 15h Main Stage
  • 3. • It’s awesome: iPhone, iPad, iPod Touch • Best Mobile App Dev Platform (by light years) • Objective-C + Foundation + Cocoa • Lots of potential users • lots of potentially paying users Why iOS
  • 4. • Software architecture for distributed systems • say web services/APIs • Client-Server • Works over HTTP & URI-based • http://api.twitter.com/1/statuses/public_timeline.json REST Quick Intro
  • 5. • There’s always something you need in “the cloud” • Data or processing power • More true on mobile • Universal: mobile, desktop, web clients • It’s easy to implement server side ( at least the basic stuff) • and everyone is doing it (twitter, github, amazon, google, ...) • It’s easy to implement on the client Why REST
  • 7. iOS REST Recipe Function Library I Use Currently iOS Boilerplate HTTP Requests ASIHTTPRequest AFNetworking JSON SBJson (AKA json-framework) JSONkit Image Caching AFNetworking (I previously used HJCache) AFNetworking Pull-To-Refresh PullToRefreshTableViewController by Leah Culver EGOTableViewPullToRefresh HUD SVProgessHUD (I previously used DSActivityView) SVProgessHUD
  • 8. • Am I connected to the internet? • Wifi or Cellular? Reachability (SystemConfiguration framework)
  • 9. NSString * const SRVR = @"api.example.com"; -(BOOL)reachable {     Reachability *r = [Reachability reachabilityWithHostName:SRVR];     NetworkStatus internetStatus = [r currentReachabilityStatus];     if(internetStatus == NotReachable) {         return NO;     }     return YES; } NotReachable ReachableViaWifi ReachableViaWWAN
  • 10. GET - (void)makeGetRequest { NSURL *url = [NSURL URLWithString:@"http://api.example.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request startSynchronous]; NSError *error = [request error]; if (!error && [request responseStatusCode] == 200) { NSString *response = [request responseString]; //NSData *responseData = [request responseData]; }
  • 11. Errors else if(error) NSLog(@"request error: %@",[error localizedDescription]); else if([request responseStatusCode] != 200) NSLog(@"server says: %@", [request responseString]); }
  • 12. •The app continues to execute •UI continues to be responsive •The request runs in the background •Two (common) ways of doing it in iOS: •Delegate •Block Asynchronous Requests
  • 13. • The delegator object has a delegate property that points to the delegate object • A delegate acts when its delegator encounters a certain event • The delegate adopts a protocol • We’ll need 2 methods: success & failure Cocoa Delegate Pattern
  • 14. Asynchronous GET - (void)makeGetRequest { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDelegate:self]; [request startAsynchronous]; } // DELEGATE METHODS: - (void)requestFinished:(ASIHTTPRequest *)request { NSString *responseString = [request responseString]; } - (void)requestFailed:(ASIHTTPRequest *)request { NSError *error = [request error]; }
  • 15. Cocoa Blocks • Ad hoc function body as an expression • Carry their code & the data they need • ideal for callbacks • We’ll need 2 blocks: success & failure
  • 16. Building Blocks - (void)makeGetRequest { NSURL *url = [NSURL URLWithString:@"http://api.example.com"]; __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^{ NSString *responseString = [request responseString]; }]; [request setFailedBlock:^{ NSError *error = [request error]; }]; [request startAsynchronous]; }
  • 18. #import "SVProgressHUD.h" - (void)makeGetRequest { NSURL *url = [NSURL URLWithString:@"http://api.example.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [SVProgressHUD showWithStatus:@"Fetching data"]; [request startSynchronous]; if (![request error]) { " [SVProgressHUD dismissWithSuccess:@"Fetch Successful"]; ... } else { " [SVProgressHUD dismissWithError:@"Fetch Failed"]; ... } }
  • 19. Where to Load Data • viewDidLoad / viewWillAppear • Make the asynchronous request • Show HUD or other “loading” indicators • LOADED = NO; • Delegate • LOADED = YES; • Reload table • Partial Load + Pagination • Load more at the end of the table
  • 22. #import "PullRefreshTableViewController.h" @interface MyTableViewController : PullRefreshTableViewController - (void)refresh {   [self performSelector:@selector(add) withObject:nil afterDelay:2.0]; } - (void) add { ... [self stopLoading]; } .m .h
  • 24. #import "UIImageView+AFNetworking.h" NSURL *imageURL = [NSURL URLWithString:@”http://example.com/picture.jpg”]; UIImageView *image = [[UIImageView alloc] init]; [image setImageWithURL:imageURL];
  • 25. Updating My Profile Picture •Modify an existing record •Authenticate •Upload a file
  • 26. ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; [request setRequestMethod:@"PUT"]; //REST modify using PUT [request setPostFormat:ASIMultipartFormDataPostFormat]; // authentication [request setUsername:username]; [request setPassword:password]; [request setFile:jpgPath forKey:@"image"]; " [request startSynchronous];
  • 27. POST & DELETE [request setRequestMethod:@"POST"]; [request setRequestMethod:@"DELETE"];
  • 28. I JSON (because it’s not XML) JSON OBJECTIVE-C/FOUNDATION Object NSDictionary Array NSArray String NSString Number NSNumber Boolean NSNumber (0 or 1)
  • 29. 1. Download a JSON string (via an http request) 2.Convert it to native data structures (parsing) 3.Use the native data structures
  • 30. Parsing [request startSynchronous]; ... SBJsonParser *prsr = [[[SBJsonParser alloc] init] autorelease]; // object NSDictionary *data = [prsr objectWithString:[request responseString]]; // or Array NSArray *data = [parsr objectWithString:[request responseString]];
  • 31. INCEPTION [{[{}]}] An array of objects with an array of objects [        {                "name":  "object1",                "sub":  [                        {                                "name":  "subobject1"                        },                        {                                "name":  "subobject2"                        }                ]        },       ] or rather JCEPTION
  • 32. NSArray *jArray = [prsr objectWithString:data]; NSDictionary *obj1 = [jArray objectAtIndex:0]; NSString *obj1Name = [obj1 objectForKey:@”name”]; NSArray *obj1SubArray = [obj1 objectForKey:@”sub”]; NSDictionary *subObj1 = [obj1SubArray objectAtIndex:0]; NSNumber *subObj1Val = [subObj1 objectForKey@”value”]; [        {                "name":  "object1",                "sub":  [                        {                                "name":  "subobject1"                        },                        {                                "value":  1                        }                ]        }, ] ...[[[prsr objectWithSring:data] objectAtIndex:0] objectForKey:@”sub]...