2

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?

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • 1
    You can use something like https://github.com/mxcl/PromiseKit – Diogo Antunes Jul 13 '16 at 14:50
  • 1
    Take also a look to the reactive paradigm (with both ReactiveCocoa and RXSwift library), it is useful for this kind of abstractions. Obviously it brings to the table a lot more functionalities than the one you need here. – Alessandro Orrù Jul 13 '16 at 14:55

1 Answers1

6

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • In particular, there is a wonderful wonderful video from last year on advanced NSOperation that tells you how to do this sort of thing coherently. – matt Jul 13 '16 at 14:52
  • Ah, I've done this before with NSOperation and had forgotten about it. I'll have another look at it. Was hoping it might be within the realms of Swift with it's fancy closures and whatnot. Will take a look at the WWDC videos. Thansk – Fogmeister Jul 13 '16 at 14:53
  • 1
    This is the one: http://asciiwwdc.com/2015/sessions/226 And there is an incredibly great code sample project that goes with it. This will totally blow your mind. – matt Jul 13 '16 at 14:54
  • Haha, great. Thanks :D – Fogmeister Jul 13 '16 at 14:54
  • OK, my mind is sufficiently blown and now I wish I could scrap the app and start again with NSOperations from the ground up. HAHA! Actually though, it's not too bad. I can use this new method for this entire system. Thanks :D – Fogmeister Jul 13 '16 at 16:36
  • I knew you'd like it. That video is really exceptional. – matt Jul 13 '16 at 16:40
  • Ok. I'm done unwrapping that code. The whole NSNotification controlling the UI thing though! Anyway, a further question. What is the licensing regarding using the NSOperstion subclasses that they have in that project? – Fogmeister Jul 13 '16 at 17:55
  • yes. Lol. I didn't understand what it said. Is there a way to translate it from legalese to English? Haha – Fogmeister Jul 13 '16 at 18:05
  • IANAL, but I do speak English. And in English, it says that as long as you don't pass the whole thing off as your own you can do whatever the heck you want. "Apple grants you a ... license ... to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms." I don't see what's hard about that. :) – matt Jul 13 '16 at 18:06
  • Ok. This is a lot more awesome than I initially thought. It allows us to drop several third party dependencies that we currently have and build the app in a much more simple way. Really really powerful. Will be using his approach from the ground up in the future. – Fogmeister Jul 15 '16 at 10:27
  • A swift framework has been created from the sample code: https://github.com/pluralsight/PSOperations – duncanc4 Nov 12 '16 at 15:00