Save 37% off PRO during our Black Friday Sale! »

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.

023a6a37e8177cb2f84a236bbce643cf?s=128

Ben Scheirman

October 26, 2012
Tweet

Transcript

  1. Effective Network Programming with Wednesday, October 24, 12

  2. Ben Scheirman CFOTDIFJSNBODPN !TVCEJHJUBM • Director

  3. Bite-sized Screencasts .com Wednesday, October 24, 12

  4. Why is this important? 99%

  5. Why is this important? Doing

  6. Why is this important? Everyone

  7. Why is this important? Everyone

  8. Exhibit A: Stuttery Scroller Wednesday, October 24, 12

  9. Exhibit A: Stuttery Scroller Accessing

  10. Exhibit B: The Perpetual Loader Wednesday, October 24, 12

  11. Exhibit B: The Perpetual Loader How

  12. Exhibit C: Slow Loader Wednesday, October 24, 12

  13. Exhibit C: Slow Loader Loading

  14. Exhibit D: Yesterday’s News Wednesday, October 24, 12

  15. Exhibit D: Yesterday’s News Caching

  16. What we’ll cover w"'/FUXPSLJOH#BTJDT w-*7&$0%*/( XJTINFMVDL w)551$BDIJOH w$BDIJOH1BUUFSOT w"1*%FTJHO5JQT Wednesday,

    October 24, 12
  17. AFNetworking Wednesday, October 24, 12

  18. Installation gem install cocoapods Podfile pod install platform :ios, “5.0”

    pod ‘AFNetworking’ Wednesday, October 24, 12
  19. Installation gem install cocoapods Podfile pod install platform :ios, “5.0”

    pod ‘AFNetworking’ Wednesday, October 24, 12
  20. Installation gem install cocoapods Podfile platform :ios, “5.0” pod ‘AFNetworking’

    pod install Wednesday, October 24, 12
  21. Installation gem install cocoapods Podfile pod install platform :ios, “5.0”

    pod ‘AFNetworking’ Wednesday, October 24, 12
  22. AFNetworking Design AFHTTPRequestOperation NSOperation AFURLConnectionOperation NSURLRequest NSURLConnection Wednesday, October 24,

    12
  23. Why NSOperation? •Queues

  24. Usage Wednesday, October 24, 12

  25. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; Wednesday, October 24, 12

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

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

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

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

    requestWithURL:url]; AFHTTPRequestOperation *operation; operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; Wednesday, October 24, 12
  30. 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
  31. 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
  32. 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
  33. 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
  34. 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
  35. 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
  36. 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
  37. Requesting JSON Wednesday, October 24, 12

  38. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; Wednesday, October 24,

    12
  39. Requesting JSON NSURL *url = [NSURL URLWithString:@”http://jsonip.com”]; NSURLRequest *request =

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

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

    [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation; operation = [[AFJSONRequestOperation alloc] Wednesday, October 24, 12
  42. 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
  43. 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
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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
  49. Requesting Images Wednesday, October 24, 12

  50. Requesting Images NSURL *imageUrl = [NSURL URLWithString: Wednesday, October 24,

    12
  51. Requesting Images NSURL *imageUrl = [NSURL URLWithString: @”http://i.imgur.com/RH1Si.jpg”]; Wednesday, October

    24, 12
  52. Requesting Images NSURL *imageUrl = [NSURL URLWithString: @”http://i.imgur.com/RH1Si.jpg”]; [imageView setImageWithURL:imageUrl];

    Wednesday, October 24, 12
  53. Say it with me now... Wednesday, October 24, 12

  54. 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
  55. 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
  56. 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
  57. Requesting XML? Wednesday, October 24, 12

  58. Requesting XML? AFXMLRequestOperation Wednesday, October 24, 12

  59. Requesting plist? Wednesday, October 24, 12

  60. Requesting plist? AFPropertyListRequestOperation Wednesday, October 24, 12

  61. Requesting raw data? Wednesday, October 24, 12

  62. Requesting raw data? AFHTTPRequestOperation Wednesday, October 24, 12

  63. API Clients

  64. Demo: app.net client Wednesday, October 24, 12

  65. What is success? 200-299 Wednesday, October 24, 12

  66. What about 404? AFNetworkingErrorDomain (check response code) calls failure block

    Wednesday, October 24, 12
  67. What about 302? call setRedirectResponseBlock: to alter behavior transparently handled

    for you Wednesday, October 24, 12
  68. Other errors Timeout No network available 401 Unauthorized 403 Forbidden

    5xx server error Wednesday, October 24, 12
  69. HTTP Caching Client Server Wednesday, October 24, 12

  70. HTTP Caching Client Server GET /customer/152.json HTTP 1.1 Host: example.com

    Wednesday, October 24, 12
  71. 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
  72. 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
  73. 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
  74. 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
  75. Leveraging Etag on the client Client Server Wednesday, October 24,

    12
  76. 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
  77. 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
  78. Leveraging Modified Date Client Server Wednesday, October 24, 12

  79. Leveraging Modified Date GET /customer/152.json HTTP 1.1 Host: example.com If-Modified-Since:

    <date> Client Server Wednesday, October 24, 12
  80. 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
  81. Etag/Last Modified on the Server Wednesday, October 24, 12

  82. Etag/Last Modified on the Server def show Wednesday, October 24,

    12
  83. Etag/Last Modified on the Server def show @customer = Customer.find(params[:id])

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

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

    fresh_when(:etag => @customer, :last_modified => @customer, Wednesday, October 24, 12
  86. 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
  87. 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
  88. 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
  89. 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
  90. Cache-Control limitations Server Wednesday, October 24, 12

  91. Cache-Control limitations Server Wednesday, October 24, 12

  92. Cache-Control limitations Server Cache-Control: max-age: 600 Wednesday, October 24, 12

  93. Cache-Control limitations Server Cache-Control: max-age: 600 Wednesday, October 24, 12

  94. Cache-Control limitations Server Cache-Control: max-age: 600 Cache-Control: max-age: 600 Wednesday,

    October 24, 12
  95. Reverse-Proxy Cache FTW Server Varnish / Squid / Nginx Wednesday,

    October 24, 12
  96. Reverse-Proxy Cache FTW Server Varnish / Squid / Nginx Wednesday,

    October 24, 12
  97. Reverse-Proxy Cache FTW Server Varnish / Squid / Nginx Wednesday,

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

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

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

    / Nginx Cache-Control: max-age: 600 Wednesday, October 24, 12
  101. 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
  102. 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
  103. .JLF %PO`UFWFSDBMMNFBHBJO Wednesday, October 24, 12

  104. 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
  105. Pros / Cons of Etag / IMS Server skips rendering

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

    User’s Profile • Customer’s Order • Activity Timeline • Yesterday’s stats Wednesday, October 24, 12
  107. Tradeoff Fresh

  108. Tradeoff Fresh

  109. Caching w/ AFNetworking Leverages NSURLCache already Wednesday, October 24, 12

  110. 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
  111. Consider alternatives SDURLCache http://github.com/steipete/SDURLCache Wednesday, October 24, 12

  112. Default Cache Location ~/Library/Caches/com.acme.app/Cache.db Wednesday, October 24, 12

  113. Wednesday, October 24, 12

  114. Switcheroo View Controller API Client Coordinator Wednesday, October 24, 12

  115. Switcheroo View Controller API Client Coordinator get data Wednesday, October

    24, 12
  116. Switcheroo View Controller API Client Coordinator get data start request

    Wednesday, October 24, 12
  117. Switcheroo View Controller API Client Coordinator get data start request

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

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

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

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

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

    (cached data) HTTP GET 200 OK (parsed response) update cache Wednesday, October 24, 12
  123. 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
  124. API Design Tips Don’t expose your internal model http://www.myspace.com/na6_build/photos/20613762 Wednesday,

    October 24, 12
  125. API Design Tips Version your API Wednesday, October 24, 12

  126. API Design Tips Send OS Version, App Version, and Device

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

    upgrade (even force) Wednesday, October 24, 12
  128. 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
  129. API Design Tips Page Large Datasets Wednesday, October 24, 12

  130. API Design Tips Build-in HTTP Caching support from day 1

    Wednesday, October 24, 12
  131. API Design Tips Take care when caching user-specific data Wednesday,

    October 24, 12
  132. API Design Tips Turn on Gzip Compression Wednesday, October 24,

    12
  133. API Design Tips Measure your API response times Wednesday, October

    24, 12
  134. Thank you! Ben Scheirman @subdigital nsscreencast.com Wednesday, October 24, 12