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.

WebApiを利用する際のOptional Bindingやクロージャを駆使したSwiftらしいコードの書き方

4,746 views

Published on

第2回 Swift 勉強会 - LT会@wantedly でLTした資料です
http://wantedly.connpass.com/event/6755/

Published in: Software

WebApiを利用する際のOptional Bindingやクロージャを駆使したSwiftらしいコードの書き方

  1. 1. WebAPIを利用する際の Optional Bindingやクロー ジャを駆使したSwiftらしい コードの書き方 ㍿キュリオシティソフトウェア 今城善矩 yimajo 第2回Swift勉強会 - LT会@wantedly 写真はスズキ株式会社Webページから
  2. 2. 前回の勉強会後 ! Optional、クロージャ、JSONのパース部分が よく分からんという話があったので QiitaのAPIを使って通信をする例で よりSwiftらしい実践的なコードの書き方を 説明しようと思います
  3. 3. 説明のためのコードの全体像について
  4. 4. APIClientTableViewController jsonEntityクラス QiitaAPI [ {title: titleA , gist_url:null, }, {title: titleB , gist_url:null, } ] class QiitaItemEntity { let title : String let gistUrlString : String? ! init(title : String) { self.title = title } } 色々省略してるけど 配列と辞書になってる
  5. 5. 実際のコードで説明
  6. 6. APIリクエストメソッドのインターフェース 引数1つ目tagName:は必須でQiitaの記事のタグを指定 引数2つ目success:はクロージャで成功時の処理 引数3つ目failure:は失敗時の処理でエラーを含む class QiitaAPIClient { ! class func items( tagName:String, success:((QiitaItemEntity[]) -> Void)?, failure:((NSError?) -> Void)?) ! }
  7. 7. メソッドの利用例 ViewControllerのメンバ変数としてQiitaItemEntityの配列 を持ち成功時にそのデータにassignしてtableViewをリ ロードする (今回の例では説明の簡素化のため、クラスメソッドにし通信が終わり次第APIClientが破棄されるた めselfを弱参照にしていない) QiitaAPIClient.items("swift", success:{(items:QiitaItemEntity[]) in //成功時のクロージャー self.qiitaItems = items self.tableView.reloadData() }, failure:nil)
  8. 8. APIリクエストを行うメソッドの 実装例
  9. 9. 長くなるので手順を分割して 説明 1. NSURLRequestを組み立てる 2. NSURLConnectionで非同期通信の用意 (AFNetworking使うとその補足がメンドイので NSURLConnectionを使った) 3. 通信後の非同期処理用クロージャでJSONパー ス時の処理(Swiftらしいコードになる)
  10. 10. 1. NSURLRequestを組み立てる //クラス変数はないがプロパティはあるのでgetterでStringを返す class var baseUrlString: String { return "https://qiita.com/api/v1" } class func itemsURL(tagName:String) -> NSURL { //Stringはプレースホルダに入れて組み立てられる return NSURL(string: "(self.baseUrlString)/tags/(tagName)/items") } let request = NSURLRequest(URL: itemsURL(tagName))
  11. 11. 2. NSURLConnectionで非同期通信 NSURLConnection.sendAsynchronousRequest( request, //さっき用意したNSURLRequest queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!, data: NSData!, error: NSError!) in // あらかじめエラー処理 if error {failure?(error); return} // nilのものをJSONパースしようとすると例外起こすので // 処理をやめる(とりあえずfailure呼び出している) if !data {failure?(nil); return} ! // (snip) 次にdataからJSONをパースしクロージャ呼出の説明 } )
  12. 12. 3. 通信後の非同期処理用クロージャ // (1)仕様上JSONがNSDictionary配列なのでキャストしつつOptional Binding if let objects = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.AllowFragments, error:&jsonError) as? NSDictionary[] { ! var items = QiitaItemEntity[]() //(2)Arrayの全ての要素がNSDictionaryだからfor inできる for dictionary : NSDictionary in objects { //(3)最後もBindingしてnilじゃない事を確認してオブジェクト作る if let title = dictionary["title"] as? String { let qiita = QiitaItemEntity(title: title) qiita.gistUrlString = dictionary["gist_url"] as? String //(5)配列の+=はapendにオーバーロードされる items += qiita } } } success(items) ! } else if jsonError { failure(jsonError) //想定外1(サーバがなぜかJSONを返していない) } else { //想定外2(レスポンスはJSONだが仕様通りのJSONでない) }
  13. 13. まとめ
  14. 14. Swiftの特徴から開発時に気 をつけること • コンパイラは変数がnilかどうかをコーディング時に気にさせてくる • 想定外のことが起こりそうな部分を最小限に留めたい思想を感じる • Foundation Frameworkにあるメソッドにはnilを引数に渡せるのに渡 すと例外になるものがあってまだ地雷っぽい(nilを渡せないように明示 してくれればいいのに…) • コンテナが型を明示するようになった • 何が入ってるかわからない時はOptional Binding • blocks的なことがクロージャになった • クロージャもOptionalにできる
  15. 15. 今回のソースコードはGitHubに公開しておきます https://github.com/yimajo/QiitaAPISwiftDemo
  16. 16. http://qiita.com/yimajo/items/32a5209bd73580d283a1 ■iOSアプリ開発のためにSwiftでクロージャを実用的に使う方法 ■Swiftでは配列の型が確定しないとfor inは扱えない(気がする) http://qiita.com/yimajo/items/afaac26a4ab0bc0bb320 ■Swiftでリソースにあるjsonファイルを読み込む http://qiita.com/yimajo/items/ca11f9a5fcf623294d26 参考 ■SwiftでWebAPIアプリを作った時の要点 http://qiita.com/himara2/items/165393baac0bd1705bfe

×