techium

このブログは何かに追われないと頑張れない人たちが週一更新をノルマに技術情報を発信するブログです。もし何か調査して欲しい内容がありましたら、@kobashinG or @muchiki0226 までいただけますと気が向いたら調査するかもしれません。

Swift x Promise

Swift x Promise

Promise

Swift で Promise パターンを実現するために、PromiseKit を使う。

mxcl/PromiseKit/ Promises for iOS and OS X

Modern development is highly asynchronous: isn’t it about time we had tools that made programming asynchronously powerful, easy and delightful?

実装例

Chaining Promises にある通り、非同期処理をチェーンさせるという実装をしてみたかったのでお試し。

chaining

  func testChaining() {
    let expectation = self.expectationWithDescription("testExample")
    firstly {
      NSURLConnection.promise(NSURLRequest(URL: NSURL(string: "https://google.com")!))
      }.then { hoge in
        NSURLConnection.promise(NSURLRequest(URL: NSURL(string: "https://yahoo.com")!))
      }.then { fuga in
        NSURLConnection.promise(NSURLRequest(URL: NSURL(string: "https://apple.com")!))
      }.then { foo in
        print(foo.description)
      }.then {
        expectation.fulfill()
      }.error { (error) in
        print(error)
    }

    self.waitForExpectationsWithTimeout(10, handler: nil)
  }

大変シンプル。
PromiseKit の中で NSURLConnection の extention が定義されており、NSURLConnection.promise とすることで promise 用に包括された非同期処理を記述できるようになっている。
こういう設計ができるようになりたい、というのはさておき今回は使用する側なので。

Building a Web API class との併用

Web API Helper クラスを自作し、それを chaining する実装例

Web API Helper クラスはこちらがちょうど参考になったのでこれをベースに使用する。
swagger-codegen/samples/client/petstore/swift/SwaggerClientTests at master · swagger-api/swagger-cod

上記を chaining してみた例が下記の通り。

  func testWebAPIHelperChaining() {
    let expectation = self.expectationWithDescription("testExample")
    let newPet = Pet()
    let category = PetstoreClient.Category()
    category.id = 1234
    category.name = "eyeColor"
    newPet.category = category
    newPet.id = 1000
    newPet.name = "Fluffy"
    newPet.status = .Available
    let newPet2 = Pet()
    newPet2.id = 1001
    newPet2.name = "Woofy"
    newPet2.status = .Available
    
    PetAPI.addPet(body: newPet)
      .then {
        PetAPI.getPetById(petId: 1000)
      }.then { pet in
        print(pet.name)
        return PetAPI.addPet(body: newPet2)
      }.then {
        PetAPI.getPetById(petId: 1001)
      }.then({ pet in
        print(pet.name)
        expectation.fulfill()
      }).error({ (error) in
        print(error)
      })
      
    
    self.waitForExpectationsWithTimeout(10, handler: nil)
  }

非常にシンプルに記述できる。
くるったようにネストさせることがなくなって大変良い。