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

URLProtocol

M
November 24, 2017

 URLProtocol

URLProtocolを使用してスタブして開発する紹介

M

November 24, 2017
Tweet

More Decks by M

Other Decks in Programming

Transcript

  1. #if DEBUG DispatchQueue.global().async { // ϞοΫσʔλΛ࡞੒ let user = User.mockData()

    // ݁Ռॲཧ } #else let request = URLRequest(url: URL(string: "https://api.test.com/ users/foo")!) let task = URLSession.shared.dataTask(with: request) { (data, response, error) in // ݁Ռॲཧ } task.resume() #endif
  2. URL Loading System The URL loading system is a set

    of classes and protocols that allow your app to access content referenced by a URL. At the heart of this technology is the NSURL class, which lets your app manipulate URLs and the resources they refer to. https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ URLLoadingSystem/URLLoadingSystem.html
  3. Foundation͕ఏڙ͍ͯ͠ΔΫϥ ε • URLͷίϯςϯπΛϩʔυ • αʔόʹσʔλΛΞοϓϩʔυ • ΫοΩʔετϨʔδͷ؅ཧ • ϨεϙϯεΩϟογϡͷ੍ޚ

    • ΞϓϦέʔγϣϯݻ༗ͷํ๏ͰͷΫϨσϯγϟϧετϨʔδͱೝ ূͷॲཧ • ΧελϜϓϩτίϧͷ֦ு
  4. URLProtocol An NSURLProtocol object handles the loading of protocol-specific URL

    data. The NSURLProtocol class itself is an abstract class that provides the infrastructure for processing URLs with a specific URL scheme. You create subclasses for any custom protocols or URL schemes that your app supports. https://developer.apple.com/documentation/foundation/urlprotocol
  5. ඞ࣮ͣ૷͠ͳ͍ͱ͍͚ͳ͍΋ͷ • class func canInit(with request: URLRequest) - > Bool

    • class func canonicalRequest(for request: URLRequest) -> URLRequest • func startLoading() • func stopLoading()
  6. override func startLoading() { // ϞοΫσʔλΛऔಘʢྫ͑͹Bundle͔ΒJSONσʔλΛऔಘʣ guard let path =

    Bundle.main.path(forResource: "user", ofType: "json"), let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else { // Τϥʔॲཧ } let client = self.client let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: ["Content-Type" : "application/ json;"]) // ϨεϙϯεΛฦ͢ client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: .notAllowed) // σʔλΛฦ͢ client?.urlProtocol(self, didLoad: data) // ௨৴Λऴྃ client?.urlProtocolDidFinishLoading(self) }
  7. override func startLoading() { ... // Τϥʔॲཧ let client =

    self.client let response = HTTPURLResponse(url: request.url!, statusCode: 500, httpVersion: "HTTP/1.1", headerFields: ["Content-Type" : "application/ json;"]) // ϨεϙϯεΛฦ͢ client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: .notAllowed) // ΤϥʔΛ࡞੒ͯ͠௨৴Λऴྃ let error = NSError(domain: "CustomURLProtocolError", code: 10001, userInfo: nil) client?.urlProtocol(self, didFailWithError: error) return .... }
  8. URLProtocolClient • URLProtocolͷαϒΫϥε͕"URL Loading System"ͱ΍ΓͱΓ͢Δϓϩτίϧ • func urlProtocol(URLProtocol, didReceive: URLResponse,

    cacheStoragePolicy: URLCache.StoragePolicy) • func urlProtocol(URLProtocol, didLoad: Data) • func urlProtocolDidFinishLoading(URLProtocol) • func urlProtocol(URLProtocol, didFailWithError: Error) • func urlProtocol(URLProtocol, didReceive: URLAuthenticationChallenge) • func urlProtocol(URLProtocol, didCancel: URLAuthenticationChallenge) • func urlProtocol(URLProtocol, wasRedirectedTo: URLRequest, redirectResponse: URLResponse) • func urlProtocol(URLProtocol, cachedResponseIsValid: CachedURLResponse)
  9. URLProtocolClient • URLProtocolͷαϒΫϥε͕"URL Loading System"ͱ΍ΓͱΓ͢Δϓϩτίϧ • func urlProtocol(URLProtocol, didReceive: URLResponse,

    cacheStoragePolicy: URLCache.StoragePolicy) • func urlProtocol(URLProtocol, didLoad: Data) • func urlProtocolDidFinishLoading(URLProtocol) • func urlProtocol(URLProtocol, didFailWithError: Error) • func urlProtocol(URLProtocol, didReceive: URLAuthenticationChallenge) • func urlProtocol(URLProtocol, didCancel: URLAuthenticationChallenge) • func urlProtocol(URLProtocol, wasRedirectedTo: URLRequest, redirectResponse: URLResponse) • func urlProtocol(URLProtocol, cachedResponseIsValid: CachedURLResponse) ੒ޭ࣌
  10. URLProtocolClient • URLProtocolͷαϒΫϥε͕"URL Loading System"ͱ΍ΓͱΓ͢Δϓϩτίϧ • func urlProtocol(URLProtocol, didReceive: URLResponse,

    cacheStoragePolicy: URLCache.StoragePolicy) • func urlProtocol(URLProtocol, didLoad: Data) • func urlProtocolDidFinishLoading(URLProtocol) • func urlProtocol(URLProtocol, didFailWithError: Error) • func urlProtocol(URLProtocol, didReceive: URLAuthenticationChallenge) • func urlProtocol(URLProtocol, didCancel: URLAuthenticationChallenge) • func urlProtocol(URLProtocol, wasRedirectedTo: URLRequest, redirectResponse: URLResponse) • func urlProtocol(URLProtocol, cachedResponseIsValid: CachedURLResponse) ࣦഊ࣌
  11. • ྫ͑͹ `application(_: didFinishLaunchingWithOptions:)`Ͱొ࿥ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:

    [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // ࢖༻ొ࿥ URLProtocol.registerClass(CustomURLProtocol.self) return true } URL Loading Systemʹొ࿥
  12. • Կ΋ҙࣝ͠ͳͯ͘ྑ͍ • ϦϦʔε༻ίʔυͦͷ··ͷ࣮૷Ͱྑ͍ let request = URLRequest(url: URL(string: "https://api.test.com/users/

    foo")!) let task = URLSession.shared.dataTask(with: request) { (data, response, error) in // ݁Ռॲཧ } task.resume() ϦΫΤετॲཧ
  13. • ྫ͑͹ίϯύΠϧFlagsͰ࣮૷Λ෼͚Δඞཁ͕ ͳ͍ #if DEBUG let path = Bundle.main.path(forResource: "user",

    ofType: "json")! let data = try! Data(contentsOf: URL(fileURLWithPath: path)) DispatchQueue.global().async { // ݁Ռॲཧ } #else let request = URLRequest(url: URL(string: "https://api.test.com/users/foo")!) let task = URLSession.shared.dataTask(with: request) { (data, response, error) in // ݁Ռॲཧ } task.resume() #endif
  14. • Կ΋ҙࣝ͠ͳͯ͘ྑ͍ • ϦϦʔε༻ίʔυͦͷ··ͷ࣮૷Ͱྑ͍ • ྫ͑͹ίϯύΠϧFlagsͰ࣮૷Λ෼͚Δඞཁ͕ͳ͍ let request = URLRequest(url:

    URL(string: "https://api.test.com/users/ foo")!) let task = URLSession.shared.dataTask(with: request) { (data, response, error) in // ݁Ռॲཧ } task.resume() ϦΫΤετॲཧ
  15. • ྫ͑͹ `application(_: didFinishLaunchingWithOptions:)`Ͱొ࿥ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:

    [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // ࢖༻ొ࿥ URLProtocol.registerClass(CustomURLProtocol.self) return true } URL Loading Systemʹొ࿥
  16. URLSession.shared • The shared session uses the shared NSURLCache, NSHTTPCookieStorage,

    and NSURLCredentialStorage objects, uses a shared custom networking protocol list (configured with registerClass(_:) and unregisterClass(_:)), and is based on a default configuration. • In other words, if you’re doing anything with caches, cookies, authentication, or custom networking protocols, you should probably be using a default session instead of the shared session. https://developer.apple.com/documentation/foundation/urlsession/1409000-shared
  17. • URLSessionConfigurationͷ var protocolClasses: [AnyClass]? ʹઃఆ let config = URLSessionConfiguration.default

    config.protocolClasses = [CustomURLProtocol.self] let session = URLSession(configuration: config) let task = session.dataTask(with: urlRequest) { (data, response, error) in ... } ಛఆͷϦΫΤετͷΈར༻
  18. • ΧελϜURLProtocolΛઃఆͨ͠URLSessionConfigurationΛݩʹ SessionManagerΛੜ੒ͯ͠ར༻ • (஫)࡞੒ͨ͠SessionManager͸Ͳ͔͜Ͱอ͓࣋ͯ͘͠ඞཁ͋Γ let config = URLSessionConfiguration.default config.protocolClasses

    = [CustomURLProtocol.self] self.manager = SessionManager(configuration: config) // อ࣋͢Δ manager.request(url).response { response in ... } AlamofireͰར༻
  19. • ΧελϜURLProtocolΛઃఆͨ͠URLSessionConfigurationΛݩʹ URLSessionAdapterɺSessionΛੜ੒ͯ͠ར༻ let config = URLSessionConfiguration.default config.protocolClasses = [CustomURLProtocol.self]

    let adapter = URLSessionAdapter(configuration: config) let session = Session(adapter: adapter) session.send(request) { (result) in ... } APIKitͰར༻
  20. Appendix • [URL Loading System]: https://developer.apple.com/library/content/ documentation/Cocoa/Conceptual/URLLoadingSystem/ URLLoadingSystem.html • [URLProtocol]:

    https://developer.apple.com/documentation/foundation/ urlprotocol • [Using NSURLProtocol with Swift]: https://www.raywenderlich.com/76735/ using-nsurlprotocol-swift • [iOS Advent Calendar 2011 5೔໨ / NSURLProtocolͷ࢖͍ํ]: http:// faultier.blog.jp/archives/1762587.html • [Using NSURLProtocol for Testing]: https://yahooeng.tumblr.com/post/ 141143817861/using-nsurlprotocol-for-testing