Search code examples
iosswiftoptimistic-locking

Best practice for API Request's Queue


What is the best practice for Swift to make an API Request's queue? I mean, while there is more than 1 API being called on a function, how to make sure the first API is getting any response first then the second API is executed?

func test() {
    getAPI1()
    getAPI2()
}

func getAPI1() {
    Connector.sharedInstance().getAPI1({ (
        data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
        
    })
}

...

I am thinking of giving a flag to indicate that there is any other API is still waiting for response so the second API that will be executed will be waiting until the flag is changed by the previously called API. But, are there any other better options?


Solution

  • Almost every Cocoa API works asynchronously, for example

    Create an enum with a generic Success type

    enum Result<T> : ErrorType {
      case Success(T)
      case Failure(NSError)
    }
    

    getAPI1 returns an NSData object on success otherwise NSError

    func getAPI1(completion:Result<NSData> -> ()) {
      var data : NSData?
      //
      if data != nil {
        completion(.Success(data!))
      } else {
        let error = NSError(domain: "my.domain", code: 9999, userInfo: [:])
        completion(.Failure(error))
      }
    }    
    

    getAPI2 has an NSData parameter and returns a dictionary [String:AnyObject] object on success otherwise NSError

    func getAPI2(data:NSData, completion:Result<[String:AnyObject]> -> ()) {
      //
      completion(.Success([String:AnyObject]()))
    }
    

    test executes both methods asynchronously depending on their results

    func test() {
      getAPI1 { (result1) in
        switch result1 {
        case .Success(let data) :
          getAPI2(data) { (result2) in
            switch result2 {
            case .Success(let dictionary) :
              dispatch_async(dispatch_get_main_queue()) {
                // update UI with the dictionary
              }
            case .Failure(let error) : print(error)
            }
          }
    
        case .Failure(let error) : print(error)
        }
      }
    }