Jordi Gallen
Jordi Gallen

Reputation: 47

Swift 4 - Call nests with PromiseKit

Good morning everyone!

I'm doing an app with Swift 4.2 with Xcode10 and calls I manage with Alomofire together with PromiseKit.

At one point I need to load a screen at the beginning of the app with the terms of use, but only if they have updated it. And if the version has changed, that same call has the URL with the new endpoint. That endpoint contains the text to be displayed.Therefore, in that last case. We would have to make two calls.

Then I explain what I want to do:

he problem is that I do not know how to make that double call blocking. So do not load the main screen without checking the version number. And without knowing if I have to show or not the screen of legal terms again. And all this is PromiseKit and nested calls.

Many thanks, for your help.

[Code updated]

let legalWarningRepository = LegalWarningRepository()
        firstly {
            legalWarningRepository.get(endpoint: "http://myserver.com/version")
            }.then { json in
                if let remoteVersion = json["version"] as? String, let 
                    legalUrl = json["legal_URL"] as? String, 
                    remoteVersion != localVersion {
                        return legalWarningRepository.get(endpoint: legalUrl)
            }
        }.done { json in
            if json == nil {
                // display main screen
            }
            else {
                // display legal terms
            }
        }.catch { err in
            print(err)
    }

And inside "legalWarningViewController" I have the get method that you have passed me:

func get(endpoint: String) -> Promise<[String: Any]> {
  return Promise { seal in
    Alamofire.request(endpoint)
      .validate()
      .responseJSON { response in
        switch response.result {
        case .success(let json):
          guard let json = json  as? [String: Any] else {
            return seal.reject(AFError.responseValidationFailed(reason: 
.dataFileNil))
          }
          seal.fulfill(json)
          case .failure(let error):
            seal.reject(error)
          }
       }
  }
}

Upvotes: 1

Views: 1083

Answers (1)

Yannick Loriot
Yannick Loriot

Reputation: 7136

On your first screen you can display an activity indicator while waiting for responses. When you have your responses you can display the appropriate view then.

In order to keep things simple you can create a generic method that "promisify" the Alamofire call:

func get(endpoint: String) -> Promise<[String: Any]> {
  return Promise { seal in
    Alamofire.request(endpoint)
      .validate()
      .responseJSON { response in
        switch response.result {
        case .success(let json):
          guard let json = json  as? [String: Any] else {
            return seal.reject(AFError.responseValidationFailed(reason: .dataFileNil))
          }
          seal.fulfill(json)
          case .failure(let error):
            seal.reject(error)
          }
       }
  }
}

Then in your the viewDidLoad or viewWillAppear of your home screen you can do this kind of logic:

firstly {
  get(endpoint: "http://myserver.com/version")
}.then { json in
  if let remoteVersion = json["version"] as? String, let legalUrl = json["legal_URL"] as? String, remoteVersion != localVersion {
    return get(endpoint: legalUrl)
  }
}.done { json in
  if json == nil {
    // display main screen
  }
  else {
    // display legal terms
  }
}.catch { err in
   print(error.localizedDescription)
}

In your case a single call may be possible if you display the legal term in a WKWebView.

firstly {
  get(endpoint: "http://myserver.com/version")
}.done { json in
  if let remoteVersion = json["version"] as? String, let legalUrl = json["legal_URL"] as? String, remoteVersion != localVersion {
    // display legal terms in a web view
  }
  // display main screen
}.catch { err in
   print(error.localizedDescription)
}

Upvotes: 1

Related Questions