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

プロジェクト内のURLを Associated Valuesで 管理してみる

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

プロジェクト内のURLを Associated Valuesで 管理してみる

Avatar for Taiki Suzuki

Taiki Suzuki

August 23, 2016
Tweet

More Decks by Taiki Suzuki

Other Decks in Programming

Transcript

  1. จࣈྻʹΑΔURLͷ؅ཧ let urlString = "https://qiita.com/api/v2/items" let queryString = "?page=1&per_page=20&query=swift+user%3Amarty-suzuki" guard

    let url = NSURL(string: urlString + queryString) else { return } let session = NSURLSession.sharedSession() let task = session.dataTaskWithURL(url) { data, response, error in //ड͚औͬͨσʔλͷॲཧ } task.resume()
  2. Associated ValuesʹΑΔURLͷ؅ཧ let query: [GetPath.SearchQuery] = [.Word("swift"), .User("marty-suzuki")] let path:

    GetPath = .Items(page: 1, perPage: 100, query: query) guard let url = NSURL(path: path) else { return } let session = NSURLSession.sharedSession() let task = session.dataTaskWithURL(url) { data, response, error in //ड͚औͬͨσʔλͷॲཧ } task.resume()
  3. GetPath Enum 1 enum GetPath { enum SearchQuery { case

    User(String) case Word(String) func toString() -> String { switch self { case .User(let name): return ("user:" + name).RFC3986Encode case .Word(let word): return word.RFC3986Encode } } } case Items(page: Int, perPage: Int, query: [SearchQuery]) //... var pathString: String { switch self { case .Items: return "/items" } } }
  4. GetPath Enum 2 extension GetPath { var queryString: String {

    switch self { case .Items(let page, let perPage, let query): let searchQueries: [String] = query.flatMap { $0.toString() } let searchQueryString = searchQueries.reduce("") { $0 == "" ? $1 : $0 + "+" + $1 } let parameters = [ URLQueryParameter(name: "page", value: page), URLQueryParameter(name: "per_page", value: perPage), URLQueryParameter(name: "query", value: searchQueryString, needsEncode: false) ] return convertParametersToString(parameters) } } private func convertParametersToString(queries: [URLQueryParameter?]) -> String { let queries: [String] = queries.flatMap { $0?.toPrameterString } let queryString: String = queries.reduce("") { $0 == "" ? $1 : $0 + "&" + $1 } return queryString } }
  5. URLQueryParameter struct URLQueryParameter { let name: String let value: String

    var toPrameterString: String { return "\(name)=\(value)" } //... init?(name: String, value: Any?, needsEncode: Bool = true) { guard let value = value, let encodedValue = URLQueryParameter.encodedValue(value, needsEncode: needsEncode) else { return nil } self.value = encodedValue self.name = name } }
  6. NSURL extension NSURL { private static let baseUrlString = "https://qiita.com/api/v2"

    convenience init?(path: GetPath) { self.init(string: NSURL.baseUrlString + path.pathString + "?" + path.queryString) } }
  7. ड͚औͬͨσʔλͷॲཧ let task = session.dataTaskWithURL(url) { data, response, error in

    if let error = error { print(error) return } guard let data = data else { return } do { let anyObject = try NSJSONSerialization.JSONObjectWithData($0.1, options: .AllowFragments) guard let array = as? [[String : NSObject]] else { return } let models: [Item] = array.flatMap({ Item(dictionary: $0) }) print(Int(response.allHeaderFields["Total-Count"] as? String ?? "")) models.forEach { print($0.title) } } catch let e as NSError { print(e) } }
  8. QiitaApiClient https://github.com/marty-suzuki/QiitaApiClient let query: [QiitaGetPath.SearchQuery] = [.Word("swift"), .User("marty-suzuki")] let method:

    QiitaHttpMethod = .Get(.Items(page: 1, perPage: 100, query: query)) QiitaApiClient.sharedClient.request(method) { (response: QiitaResponse<[QiitaItem]>) in switch response.result { case .Success(let models): print(response.totalCount) models.forEach { print($0.title) } case .Failure(let error): print(error) } }