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

Effective Network Programming in iOS 7

Effective Network Programming in iOS 7

Presented at Mobile Developer Summit Oct 11th in Bangalore, India

023a6a37e8177cb2f84a236bbce643cf?s=128

Ben Scheirman

October 11, 2013
Tweet

Transcript

  1. Effective Network Programming with iOS 7 Wednesday, October 9, 13

  2. Ben Scheirman CFOTDIFJSNBODPN !TVCEJHJUBM • Director

  3. Wednesday, October 9, 13

  4. Bite-sized Screencasts .com Weekly

  5. Why is this important? 99%

  6. Why is this important? Doing

  7. Why is this important? Too

  8. Exhibit A: Stuttery Scroller Wednesday, October 9, 13

  9. Exhibit A: Stuttery Scroller Accessing

  10. Exhibit B: The Perpetual Loader Wednesday, October 9, 13

  11. Exhibit B: The Perpetual Loader How

  12. Exhibit C: Slow Loader Wednesday, October 9, 13

  13. Exhibit C: Slow Loader Loading

  14. Exhibit D: Yesterday’s News Wednesday, October 9, 13

  15. Exhibit D: Yesterday’s News Caching

  16. What we’ll cover w /463-4FTTJPO#BTJDT w -*7&$0%*/( XJTINFMVDL w "'/FUXPSLJOH

    w )551$BDIJOH w $BDIJOH1BUUFSOT w "1*%FTJHO5JQT Wednesday, October 9, 13
  17. NSURLConnection Invented for Safari ~2000, made public in 2003 Poor

    separation of settings, config, cache Now replaced by NSURLSession classes Wednesday, October 9, 13
  18. NSURLConnection Invented for Safari ~2000, made public in 2003 Poor

    separation of settings, config, cache Now replaced by NSURLSession classes Wednesday, October 9, 13
  19. NSURLSession Still use NSURLRequest Configurable Container (isolation w/ 3rd party

    libraries) Improved auth Rich Callbacks Wednesday, October 9, 13
  20. NSURLSession Wednesday, October 9, 13

  21. NSURLSession Wednesday, October 9, 13

  22. NSURLSession Wednesday, October 9, 13

  23. NSURLSession Class Family NSURLSessionConfiguration NSURLSessionTask NSURLSessionDelegate NSURLSession Wednesday, October 9,

    13
  24. NSURLSession NSURLSession Interface for issuing network calls against a server

    Likely use case: 1 session per API Wednesday, October 9, 13
  25. NSURLSessionDelegate Delegate methods for a session: Used for connect level

    authentication challenges NTLM, Kerberos, Client certificates - URLSession:didBecomeInvalidWithError: - URLSession:didReceiveChallenge:completionHandler: Wednesday, October 9, 13
  26. NSURLSessionTask Wednesday, October 9, 13

  27. NSURLSessionTaskDelegate Delegate methods for a request: Only need to implement

    for fine-grained control - URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler: - URLSession:task:didReceiveChallenge:completionHandler: - URLSession:task:needNewBodyStream: - URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend: - URLSession:task:didCompleteWithError: Wednesday, October 9, 13
  28. NSURLSessionDataTaskDelegate Delegate methods for a data request: Only need to

    implement for fine-grained control - URLSession:dataTask:didReceiveChallenge:completionHandler: - URLSession:dataTask:didBecomeDownloadTask: - URLSession:dataTask:didReceiveData: - URLSession:dataTask:willCacheResponse:completionHandler: Wednesday, October 9, 13
  29. NSURLSessionDownloadDelegate - URLSession:downloadTask:didFinishDownloadingToURL: -URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: - URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes: Wednesday, October 9, 13

  30. Requesting Images Wednesday, October 9, 13

  31. Have you ever seen this? NSURL *imageUrl = [NSURL URLWithString:

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

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

    @”http://i.imgur.com/kwpjYwQ.jpg”]; NSData *imageData = [NSData dataWithContentsOfURL:imageUrl]; UIImage *image = [UIImage imageWithData:imageData]; [imageView setImage:image]; Wednesday, October 9, 13
  34. In case you were wondering... Wednesday, October 9, 13

  35. Demo •Demo: Download an image with NSURLSessionDownloadTask Wednesday, October 9,

    13
  36. NSURLSessionDataTask •Represents GET/PUT/POST/DELETE •Handle completion callback •If error is present,

    request failed Wednesday, October 9, 13
  37. What constitutes an error? • Connection failed • Timeouts •

    Host invalid • Bad URL • Too many redirects • ... dozens more (check URL Loading System Error Codes) Wednesday, October 9, 13
  38. Demo •Demo: Searching the iTunes Store Wednesday, October 9, 13

  39. AFNetworking Wednesday, October 9, 13

  40. AFNetworking 2.0 Wednesday, October 9, 13

  41. Installation gem install cocoapods Podfile pod install platform :ios, "7.0"

    pod 'AFNetworking', '2.0' Wednesday, October 9, 13
  42. Installation gem install cocoapods Podfile pod install platform :ios, "7.0"

    pod 'AFNetworking', '2.0' Wednesday, October 9, 13
  43. Installation Podfile pod install platform :ios, "7.0" pod 'AFNetworking', '2.0'

    gem install cocoapods Wednesday, October 9, 13
  44. Installation Podfile pod install platform :ios, "6.0" pod 'AFNetworking' platform

    :ios, "7.0" pod 'AFNetworking', '2.0' gem install cocoapods Wednesday, October 9, 13
  45. AFNetworking 1.0 Design AFHTTPRequestOperation NSOperation AFURLConnectionOperation NSURLRequest NSURLConnection Wednesday, October

    9, 13
  46. AFNetworking 2.0 Design AFHTTPSessionManager NSObject AFURLSessionManager NSURLSession NSURLSessionConfiguration NSURLSessionTask Wednesday,

    October 9, 13
  47. Serializers AFJSONSerializer AFURLSessionManager Wednesday, October 9, 13

  48. Usage Wednesday, October 9, 13

  49. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; Wednesday, October 9, 13

  50. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    Wednesday, October 9, 13
  51. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; Wednesday, October 9, 13
  52. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] Wednesday, October 9, 13
  53. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config]; Wednesday, October 9, 13
  54. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config]; manager.responseSerializer = [[AFJSONSerializer alloc] init]; Wednesday, October 9, 13
  55. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config]; manager.responseSerializer = [[AFJSONSerializer alloc] init]; [manager GET:url parameters:nil completion:^(NSURLSessionDataTask *task, Wednesday, October 9, 13
  56. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config]; manager.responseSerializer = [[AFJSONSerializer alloc] init]; [manager GET:url parameters:nil completion:^(NSURLSessionDataTask *task, id responseObject) { Wednesday, October 9, 13
  57. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config]; manager.responseSerializer = [[AFJSONSerializer alloc] init]; [manager GET:url parameters:nil completion:^(NSURLSessionDataTask *task, id responseObject) { // handle success Wednesday, October 9, 13
  58. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config]; manager.responseSerializer = [[AFJSONSerializer alloc] init]; [manager GET:url parameters:nil completion:^(NSURLSessionDataTask *task, id responseObject) { // handle success } failure:^(NSURLSessionDataTask *task, NSError *error) { Wednesday, October 9, 13
  59. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config]; manager.responseSerializer = [[AFJSONSerializer alloc] init]; [manager GET:url parameters:nil completion:^(NSURLSessionDataTask *task, id responseObject) { // handle success } failure:^(NSURLSessionDataTask *task, NSError *error) { // handle failure Wednesday, October 9, 13
  60. Usage NSURL *url = [NSURL URLWithString:@”http://google.com”]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration

    defaultConfiguration]; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config]; manager.responseSerializer = [[AFJSONSerializer alloc] init]; [manager GET:url parameters:nil completion:^(NSURLSessionDataTask *task, id responseObject) { // handle success } failure:^(NSURLSessionDataTask *task, NSError *error) { // handle failure }]; Wednesday, October 9, 13
  61. Requesting Images Wednesday, October 9, 13

  62. Requesting Images NSURL *imageUrl = [NSURL URLWithString: Wednesday, October 9,

    13
  63. Requesting Images NSURL *imageUrl = [NSURL URLWithString: @”http://i.imgur.com/kwpjYwQ.jpg”]; Wednesday, October

    9, 13
  64. Requesting Images NSURL *imageUrl = [NSURL URLWithString: @”http://i.imgur.com/kwpjYwQ.jpg”]; [imageView setImageWithURL:imageUrl];

    Wednesday, October 9, 13
  65. Requesting XML? Wednesday, October 9, 13

  66. Requesting XML? AFXMLResponseSerializer Wednesday, October 9, 13

  67. Requesting plist? Wednesday, October 9, 13

  68. Requesting plist? AFPropertyListResponseSerializer Wednesday, October 9, 13

  69. Requesting a custom data format? Wednesday, October 9, 13

  70. Requesting a custom data format? MyCustomResponseSerializer Wednesday, October 9, 13

  71. Demo: app.net client Wednesday, October 9, 13

  72. Other AFNetworking Goodies AFHTTPSessionManager setSecurityPolicy [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey] Wednesday, October 9,

    13
  73. Other AFNetworking Goodies UIActivityIndicatorView+AFNetworking.h [indicator setAnimatingWithStateOfTask:task] Wednesday, October 9, 13

  74. HTTP Status Code Cheat Sheet 1xx - Not Used 2xx

    - Thumbs Up 3xx - It's over there 4xx - You messed up 5xx - We messed up Wednesday, October 9, 13
  75. HTTP Caching Client Server Wednesday, October 9, 13

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

    Wednesday, October 9, 13
  77. 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 9, 13
  78. 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 9, 13
  79. 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 9, 13
  80. 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 9, 13
  81. Leveraging Etag on the client Client Server Wednesday, October 9,

    13
  82. Leveraging Etag on the client GET /customer/152.json HTTP 1.1 Host:

    example.com If-None-Match:“e6482391249374127ca94128” Client Server Wednesday, October 9, 13
  83. 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 9, 13
  84. Leveraging Modified Date Client Server Wednesday, October 9, 13

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

    <date> Client Server Wednesday, October 9, 13
  86. 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 9, 13
  87. Etag/Last Modified on the Server Wednesday, October 9, 13

  88. Etag/Last Modified on the Server def show Wednesday, October 9,

    13
  89. Etag/Last Modified on the Server def show @band = Band.find(params[:id])

    Wednesday, October 9, 13
  90. Etag/Last Modified on the Server def show @band = Band.find(params[:id])

    fresh_when(:etag => @band, Wednesday, October 9, 13
  91. Etag/Last Modified on the Server def show @band = Band.find(params[:id])

    fresh_when(:etag => @band, :last_modified => @band, Wednesday, October 9, 13
  92. Etag/Last Modified on the Server def show @band = Band.find(params[:id])

    fresh_when(:etag => @band, :last_modified => @band, :public => true) Wednesday, October 9, 13
  93. Etag/Last Modified on the Server def show @band = Band.find(params[:id])

    fresh_when(:etag => @band, :last_modified => @band, :public => true) expires_in 10.minutes, :public => true Wednesday, October 9, 13
  94. Etag/Last Modified on the Server def show @band = Band.find(params[:id])

    fresh_when(:etag => @band, :last_modified => @band, :public => true) expires_in 10.minutes, :public => true end Wednesday, October 9, 13
  95. Etag/Last Modified on the Server def show @band = Band.find(params[:id])

    fresh_when(:etag => @band, :last_modified => @band, :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 9, 13
  96. Cache-Control limitations Server Wednesday, October 9, 13

  97. Cache-Control limitations Server Wednesday, October 9, 13

  98. Cache-Control limitations Server Cache-Control: max-age: 600 Wednesday, October 9, 13

  99. Cache-Control limitations Server Cache-Control: max-age: 600 Wednesday, October 9, 13

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

    October 9, 13
  101. Reverse-Proxy Cache FTW Server Varnish / Squid / Nginx Wednesday,

    October 9, 13
  102. Reverse-Proxy Cache FTW Server Varnish / Squid / Nginx Wednesday,

    October 9, 13
  103. Reverse-Proxy Cache FTW Server Varnish / Squid / Nginx Wednesday,

    October 9, 13
  104. Reverse-Proxy Cache FTW Server Cache-Control: max-age: 600 Varnish / Squid

    / Nginx Wednesday, October 9, 13
  105. Reverse-Proxy Cache FTW Server Cache-Control: max-age: 600 Varnish / Squid

    / Nginx Cache-Control: max-age: 600 Wednesday, October 9, 13
  106. Reverse-Proxy Cache FTW Server Cache-Control: max-age: 600 Varnish / Squid

    / Nginx Cache-Control: max-age: 600 Wednesday, October 9, 13
  107. 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 9, 13
  108. 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 9, 13
  109. .JLF %PO`UFWFSDBMMNFBHBJO Wednesday, October 9, 13

  110. Pros / Cons of Cache-Control Client doesn’t wait for response

    Server spends no resources But, clients may render stale data Wednesday, October 9, 13
  111. Pros / Cons of Etag / IMS Server skips rendering

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

    User’s Profile • Customer’s Order • Activity Timeline • Yesterday’s stats Wednesday, October 9, 13
  113. Tradeoff Fresh

  114. Caching w/ NSURLSession Leverages NSURLCache already Use default session configuration

    or customize cache settings Use ephemeral configuration to disable caching Wednesday, October 9, 13
  115. Caching w/ NSURLSession Customize if needed NSURLCache *cache = [[NSURLCache

    alloc] initWithMemoryCapacity:1024*1024*10 diskCapacity:1024*1024*50 diskPath:nil]; [sessionConfiguration setURLCache:cache]; Wednesday, October 9, 13
  116. Default Cache Location ~/Library/Caches/com.acme.app/Cache.db Wednesday, October 9, 13

  117. Wednesday, October 9, 13

  118. Switcheroo View Controller API Client Coordinator Wednesday, October 9, 13

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

    9, 13
  120. Switcheroo View Controller API Client Coordinator get data start request

    Wednesday, October 9, 13
  121. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) Wednesday, October 9, 13
  122. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET Wednesday, October 9, 13
  123. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET Wednesday, October 9, 13
  124. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET 200 OK Wednesday, October 9, 13
  125. Switcheroo View Controller API Client Coordinator get data start request

    (cached data) HTTP GET 200 OK (parsed response) Wednesday, October 9, 13
  126. Switcheroo View Controller API Client Coordinator get data start request

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

    (cached data) HTTP GET 200 OK (parsed response) (parsed response) update cache Wednesday, October 9, 13
  128. API Design Tips Don’t expose your internal model http://www.myspace.com/na6_build/photos/20613762 Wednesday,

    October 9, 13
  129. API Design Tips Version your API Wednesday, October 9, 13

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

    Name as headers Device Name OS Version App Version Wednesday, October 9, 13
  131. API Design Tips Have a way to notify clients to

    upgrade (even force) Wednesday, October 9, 13
  132. 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 9, 13
  133. API Design Tips Page Large Datasets Wednesday, October 9, 13

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

    Wednesday, October 9, 13
  135. API Design Tips Take care when caching user-specific data Wednesday,

    October 9, 13
  136. API Design Tips Turn on Gzip Compression Wednesday, October 9,

    13
  137. API Design Tips Measure your API response times Wednesday, October

    9, 13
  138. Thank you! Ben Scheirman @subdigital @bens (adn) @nsscreencast Wednesday, October

    9, 13