swift3grand-central-dispatchnsoperationqueuecksubscription

Sequential Network Requests in Swift 3


I have multiple network requests that need to happen in sequential order. They must wait until the previous has finished and received its response from the server.

Right now I have a callback pyramid of death. Is there a more automated way of doing this? I tried an OperationQueue but it doesn't wait for the requests to finish before advancing to the next request even with it set to do one request at a time.

For what it's worth, .save is a network request to CloudKit. There is no CloudKit subscription queue like there is with other CloudKit operations.

self.privateDB.save(subscriptions[0]){ savedSubscription, error in
  //Request 1 is done
  self.privateDB.save(subscriptions[1]){ savedSubscription, error in
    //Request 2 is done
    self.privateDB.save(subscriptions[2]){ savedSubscription, error in
      //All 3 requests are done
    }
  }
}

I tried a DispatchGroup but this doesn't seem to work. All the requests seem to fire before waiting for a response.

let group = DispatchGroup()

//Create a subscription for every record type
for subscription in subscriptions{
  group.enter()
  //...
  self.privateDB.save(subscription){ savedSubscription, error in
    group.leave()
  }    
}
group.wait()

Any ideas?


Solution

  • You should be able to create one or more CKModifySubscriptionsOperation to save the subscriptions, then use CKDatabase.add() to run them. If you need them to run in order, set up dependencies between them to ensure they run in order:

    let subscriptionOp1 = CKModifySubscriptionsOperation(subscriptionsToSave: subscriptions[0], subscriptionsToDelete: nil)
    let subscriptionOp2 = CKModifySubscriptionsOperation(subscriptionsToSave: subscriptions[1], subscriptionsToDelete: nil)
    let subscriptionOp3 = CKModifySubscriptionsOperation(subscriptionsToSave: subscriptions[2], subscriptionsToDelete: nil)
    
    subscriptionOp2.addDependency(subscriptionOp1)
    subscriptionOp3.addDependency(subscriptionOp2)
    
    database.add(subscriptionOp1)
    database.add(subscriptionOp2)
    database.add(subscriptionOp3)