Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Effective Network Programming w/ AFNetworking

Effective Network Programming w/ AFNetworking

Very few apps these days are self-contained silos. More often than not, your app will need to consume data from external sources. In this session, you'll learn how to properly write networking code so that you don't block threads, don't fetch data you don't need, and cache the right data the right way. You'll learn about an excellent framework called AFNetworking to simplify your networking code. And you'll also see some practical examples such as fetching images asynchronously to update a UITableView.

Ben Scheirman

October 26, 2012
Tweet

More Decks by Ben Scheirman

Other Decks in Programming

Transcript

  1. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; Wednesday, October 24, 12
  2. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] Wednesday, October 24, 12
  3. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; Wednesday, October 24, 12
  4. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^(AFHTTPRequestOperation *operation, Wednesday, October 24, 12
  5. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { Wednesday, October 24, 12
  6. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { // handle success Wednesday, October 24, 12
  7. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { // handle success } failure:^(AFHTTPRequestOperation *operation, NSError *error) { Wednesday, October 24, 12
  8. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { // handle success } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // handle failure Wednesday, October 24, 12
  9. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { // handle success } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // handle failure }]; Wednesday, October 24, 12
  10. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLRequest *request = [NSURLRequest

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { // handle success } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // handle failure }]; [operation start]; Wednesday, October 24, 12
  11. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; Wednesday, October 24, 12
  12. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; operation = [[AFJSONRequestOperation alloc] Wednesday, October 24, 12
  13. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; operation = [[AFJSONRequestOperation alloc] initWithRequest:request]; Wednesday, October 24, 12
  14. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; operation = [[AFJSONRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^( Wednesday, October 24, 12
  15. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; operation = [[AFJSONRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^( AFHTTPRequestOperation *operation, id responseObject) { Wednesday, October 24, 12
  16. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; operation = [[AFJSONRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^( AFHTTPRequestOperation *operation, id responseObject) { // responseObject is already parsed Wednesday, October 24, 12
  17. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; operation = [[AFJSONRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^( AFHTTPRequestOperation *operation, id responseObject) { // responseObject is already parsed } failure:^(AFHTTPRequestOperation *operation, NSError *error) { Wednesday, October 24, 12
  18. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; operation = [[AFJSONRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^( AFHTTPRequestOperation *operation, id responseObject) { // responseObject is already parsed } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // handle failure Wednesday, October 24, 12
  19. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; operation = [[AFJSONRequestOperation alloc] initWithRequest:request]; [operation setCompletionWithSuccess:^( AFHTTPRequestOperation *operation, id responseObject) { // responseObject is already parsed } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // handle failure }]; Wednesday, October 24, 12
  20. Have you ever seen this? NSURL *imageUrl = [NSURL URLWithString:

    @”http://i.imgur.com/RH1Si.jpg”]; NSData *imageData = [NSData dataWithContentsOfURL:imageUrl]; UIImage *image = [UIImage imageWithData:imageData]; [imageView setImage:image]; Wednesday, October 24, 12
  21. Have you ever seen this? NSURL *imageUrl = [NSURL URLWithString:

    @”http://i.imgur.com/RH1Si.jpg”]; NSData *imageData = [NSData dataWithContentsOfURL:imageUrl]; UIImage *image = [UIImage imageWithData:imageData]; [imageView setImage:image]; WRONG Wednesday, October 24, 12
  22. Have you ever seen this? NSURL *imageUrl = [NSURL URLWithString:

    @”http://i.imgur.com/RH1Si.jpg”]; NSData *imageData = [NSData dataWithContentsOfURL:imageUrl]; UIImage *image = [UIImage imageWithData:imageData]; [imageView setImage:image]; Wednesday, October 24, 12
  23. HTTP Caching Client Server HTTP/1.1 200 OK Content-Type: application/json Content-Length:

    37142 Etag:“e6482391249374127ca94128” Cache-Control:max-age=60, public Date:Sun, 21 Oct 2012 16:15:37 GET /customer/152.json HTTP 1.1 Host: example.com Wednesday, October 24, 12
  24. HTTP Caching GET /customer/152.json HTTP 1.1 Host: example.com Client Server

    HTTP/1.1 200 OK Content-Type: application/json Content-Length: 37142 Etag:“e6482391249374127ca94128” Cache-Control:max-age=60, public Date:Sun, 21 Oct 2012 16:15:37 Wednesday, October 24, 12
  25. HTTP Caching GET /customer/152.json HTTP 1.1 Host: example.com Client Server

    HTTP/1.1 200 OK Content-Type: application/json Content-Length: 37142 Etag:“e6482391249374127ca94128” Cache-Control:max-age=60, public Date:Sun, 21 Oct 2012 16:15:37 Wednesday, October 24, 12
  26. HTTP Caching GET /customer/152.json HTTP 1.1 Host: example.com Client Server

    HTTP/1.1 200 OK Content-Type: application/json Content-Length: 37142 Etag:“e6482391249374127ca94128” Cache-Control:max-age=60, public Date:Sun, 21 Oct 2012 16:15:37 Wednesday, October 24, 12
  27. Leveraging Etag on the client GET /customer/152.json HTTP 1.1 Host:

    example.com If-None-Match:“e6482391249374127ca94128” Client Server Wednesday, October 24, 12
  28. Leveraging Etag on the client GET /customer/152.json HTTP 1.1 Host:

    example.com If-None-Match:“e6482391249374127ca94128” Client Server HTTP/1.1 304 Not Modified < no response body > Wednesday, October 24, 12
  29. Leveraging Modified Date GET /customer/152.json HTTP 1.1 Host: example.com If-Modified-Since:

    <date> Client Server HTTP/1.1 304 Not Modified < no response body > Wednesday, October 24, 12
  30. Etag/Last Modified on the Server def show @customer = Customer.find(params[:id])

    fresh_when(:etag => @customer, Wednesday, October 24, 12
  31. Etag/Last Modified on the Server def show @customer = Customer.find(params[:id])

    fresh_when(:etag => @customer, :last_modified => @customer, Wednesday, October 24, 12
  32. Etag/Last Modified on the Server def show @customer = Customer.find(params[:id])

    fresh_when(:etag => @customer, :last_modified => @customer, :public => true) Wednesday, October 24, 12
  33. Etag/Last Modified on the Server def show @customer = Customer.find(params[:id])

    fresh_when(:etag => @customer, :last_modified => @customer, :public => true) expires_in 10.minutes, :public => true Wednesday, October 24, 12
  34. Etag/Last Modified on the Server def show @customer = Customer.find(params[:id])

    fresh_when(:etag => @customer, :last_modified => @customer, :public => true) expires_in 10.minutes, :public => true end Wednesday, October 24, 12
  35. Etag/Last Modified on the Server def show @customer = Customer.find(params[:id])

    fresh_when(:etag => @customer, :last_modified => @customer, :public => true) expires_in 10.minutes, :public => true end Note: server still does a db query, but doesn’t render a template Saves on rendering & bandwidth for response transfer Wednesday, October 24, 12
  36. Reverse-Proxy Cache FTW Server Cache-Control: max-age: 600 Varnish / Squid

    / Nginx Cache-Control: max-age: 600 Wednesday, October 24, 12
  37. Reverse-Proxy Cache FTW Server Cache-Control: max-age: 600 Varnish / Squid

    / Nginx Cache-Control: max-age: 600 Wednesday, October 24, 12
  38. Reverse-Proxy Cache FTW Server Cache-Control: max-age: 600 Cache-Control: max-age: 600

    Varnish / Squid / Nginx Cache-Control: max-age: 600 Wednesday, October 24, 12
  39. Leverage Cache-Control? HTTP/1.1 200 OK Content-Type: application/json Content-Length: 37142 Etag:“e6482391249374127ca94128”

    Cache-Control:max-age=9999999999, public Date:Sun, 21 Oct 2012 16:15:37 GMT Wednesday, October 24, 12
  40. Pros / Cons of Cache-Control Client doesn’t wait for response

    Server spends no resources But, clients may render stale data Wednesday, October 24, 12
  41. Pros / Cons of Etag / IMS Server skips rendering

    Miniscule data transfer Appears instantaneous* But, server still doing a db query Wednesday, October 24, 12
  42. Reason about your data • List of US States •

    User’s Profile • Customer’s Order • Activity Timeline • Yesterday’s stats Wednesday, October 24, 12
  43. Caching w/ AFNetworking Customize if needed NSURLCache *cache = [[NSURLCache

    alloc] initWithMemoryCapacity:1024*1024*10 diskCapacity:1024*1024*50 diskPath:nil]; [NSURLCache setSharedURLCache:cache]; Wednesday, October 24, 12
  44. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET Wednesday, October 24, 12
  45. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET Wednesday, October 24, 12
  46. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET 200 OK Wednesday, October 24, 12
  47. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET 200 OK (parsed response) Wednesday, October 24, 12
  48. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET 200 OK (parsed response) update cache Wednesday, October 24, 12
  49. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET 200 OK (parsed response) (parsed response) update cache Wednesday, October 24, 12
  50. API Design Tips Send OS Version, App Version, and Device

    Name as headers Device Name OS Version App Version Wednesday, October 24, 12
  51. API Design Tips Have a way to notify clients to

    upgrade (even force) Wednesday, October 24, 12
  52. API Design Tips • Techniques for permeating deletes • Valid

    ID Check • Client requests changes, server returns a set of new records, changed records, and deleted record ids Wednesday, October 24, 12