Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

OSSから学ぶSwift実践テクニック

1,566 views

Published on

Kyobashi.swiftで発表した内容です。

Published in: Technology
  • Be the first to comment

OSSから学ぶSwift実践テクニック

  1. 1. OSSから学ぶ Swift実践テクニック Takahashi Yosuke @yousan
  2. 2. 自己紹介 • Takahashi Yosuke • 株式会社ネクスト
 HOME Sアプリ • モバイルアプリエンジニア • 趣味 テニス
 錦織に似ていると言われる
  3. 3. OSSを使う前に コードリーディングしてみると いろいろ勉強になる
  4. 4. Alamofire https://github.com/Alamofire/Alamofire
  5. 5. ProtocolとExtensionで 組み込み型を抽象化
  6. 6. request Alamofire.request(.GET, "https://httpbin.org/get") README.md
  7. 7. requestの定義 public func request( method: Method, _ URLString: URLStringConvertible, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = .URL, headers: [String: String]? = nil) -> Request { return Manager.sharedInstance.request( method, URLString, parameters: parameters, encoding: encoding, headers: headers ) } Stringじゃない! Alamofire.swift
  8. 8. URLStringConvertible public protocol URLStringConvertible { ∼中略∼ var URLString: String { get } } extension String: URLStringConvertible { public var URLString: String { return self } } extension NSURL: URLStringConvertible { public var URLString: String { return absoluteString } } extension NSURLComponents: URLStringConvertible { public var URLString: String { return URL!.URLString } } extension NSURLRequest: URLStringConvertible { public var URLString: String { return URL!.URLString } } String NSURL NSURLComponents NSURLRequest 全てをrequestの引数に使える Alamofire.swift
  9. 9. Protocolごとに Extensionを分ける
  10. 10. public struct Response<Value, Error: ErrorType> { public let request: NSURLRequest? public let response: NSHTTPURLResponse? public let data: NSData? public let result: Result<Value, Error> public init(request: NSURLRequest?, response: NSHTTPURLResponse?, data: NSData?, result: Result<Value, Erro self.request = request self.response = response self.data = data self.result = result } } extension Response: CustomStringConvertible { public var description: String { return result.debugDescription } } extension Response: CustomDebugStringConvertible { public var debugDescription: String { var output: [String] = [] output.append(request != nil ? "[Request]: (request!)" : "[Request]: nil") output.append(response != nil ? "[Response]: (response!)" : "[Response]: nil") output.append("[Data]: (data?.length ?? 0) bytes") output.append("[Result]: (result.debugDescription)") return output.joinWithSeparator("n") } } Response.swift(コメント省略)
  11. 11. 普通に書くとこんな感じ public struct Response<Value, Error: ErrorType>: CustomStringConvertible, CustomDebugStringConvertible { public let request: NSURLRequest? public let response: NSHTTPURLResponse? public let data: NSData? public let result: Result<Value, Error> public init(request: NSURLRequest?, response: NSHTTPURLResponse?, data: NSData?, result: Result<Value, Erro self.request = request self.response = response self.data = data self.result = result } // MARK: - CustomStringConvertible public var description: String { return result.debugDescription } // MARK: - CustomDebugStringConvertible public var debugDescription: String { var output: [String] = [] output.append(request != nil ? "[Request]: (request!)" : "[Request]: nil") output.append(response != nil ? "[Response]: (response!)" : "[Response]: nil") output.append("[Data]: (data?.length ?? 0) bytes") output.append("[Result]: (result.debugDescription)") return output.joinWithSeparator("n") } }
  12. 12. extension使うと見やすい 各Protocolとメソッドの対応が、MARKで区切るより 見やすい。 Protocolとメソッドが近い、括弧によるグルーピング 各Protocolごとに関連するメソッドやサブタイプなどを まとめておけば管理も簡単。 Protocolが不要になったらextensionの範囲丸ごと消せばいい ※ただし、例えばCustomStringConvertibleのextension内に descriptionがある保証はないし、関係ないメソッドが書かれる可能 性もあるので注意。
  13. 13. メソッドチェーンで requestを使いやすく
  14. 14. public func authenticate(usingCredential credential: NSURLCredential) -> Self { delegate.credential = credential return self } public func progress(closure: ((Int64, Int64, Int64) -> Void)? = nil) -> Self { if let uploadDelegate = delegate as? UploadTaskDelegate { uploadDelegate.uploadProgress = closure } else if let dataDelegate = delegate as? DataTaskDelegate { dataDelegate.dataProgress = closure } else if let downloadDelegate = delegate as? DownloadTaskDelegate { downloadDelegate.downloadProgress = closure } return self } public func stream(closure: (NSData -> Void)? = nil) -> Self { if let dataDelegate = delegate as? DataTaskDelegate { dataDelegate.dataStream = closure } return self } Request.swift オプションを追加したついでに 最後にselfを返す
  15. 15. 大量オプションでも見やすい Alamofire.request(.GET, “https://httpbin.org/") .authenticate(usingCredential: credential) .progress(closure) .validate(statusCode: 200..<300) .validate(contentType: ["application/json"]) .response { response in print(response) } ・余分な変数が不要 ・書きやすいし読みやすい
  16. 16. まとめ コードを書くのも大切だけど 他人のコードを読むのも重要

×