Fogmeister Fogmeister - 4 months ago 29
Swift Question

Chaining multiple async functions in Swift

I'm trying to write a series of functions that will validate the user's information before asking them to confirm something. (Imagine a shopping app).


  1. I first have to check that the user has added a card.

  2. Then I have to check that they have sufficient balance.

  3. Then I can ask them to confirm the payment.



I can write the async method to check the card something like ...

func checkHasCard(completion: (Bool) -> ()) {
// go to the inter webs
// get the card
// process data
let hasCard: Bool = // the user has a card or not.
completion(hasCard)
}


This can be run like this...

checkHasCard {
hasCard in
if hasCard {
print("YAY!")
} else {
print("BOO!")
}
}


But... now, based off that I have to do various things. If the user does have a card I then need to continue onwards and check there is sufficient balance (in much the same way). If the user does not have a card I present a screen for them to add their card.

But it gets messy...

checkHasCard {
hasCard in
if hasCard {
// check balance
print("YAY!")
checkBalance {
hasBalance in
if hasBalance {
// WHAT IS GOING ON?!
print("")
} else {
// ask to top up the account
print("BOO!")
}
}
} else {
// ask for card details
print("BOO!")
}
}


What I'd like instead is something along the lines of this...

checkHasCard() // if no card then show card details screen
.checkBalance() // only run if there is a card ... if no balance ask for top up
.confirmPayment()


This looks much more "swifty" but I'm not sure how to get closer to something like this.

Is there a way?

Answer

Asynchronous operations, ordered and with dependencies? You're describing NSOperation.

Certainly you can chain tasks using GCD:

DispatchQueue.main.async {
    // do something
    // check something...
    // and then:
    DispatchQueue.main.async {
        // receive info from higher closure
        // and so on
    }
}

But if your operations are complex, e.g. they have delegates, that architecture completely breaks down. NSOperation allows complex operations to be encapsulated in just the way you're after.