Developing iOS REST Applications
- 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];
}
- 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
- 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];
- 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
- 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]...