lundi 14 décembre 2015

How to send events to all listeners *except* the caller of the current function

It's not really about Swift or iOS but more about programming patterns in general. How would you go about performing an async change that can affect multiple parts of your app when the calling part can also subscribe to those changes?

For instance:

// Account manager
class AccountManager {
    func updateEmail(email: String) -> Promise<Void> {
        return API.updateEmail(accountId, email: email).then { _ -> Void in
            NSNotificationCenter.defaultCenter().postNotificationName(EmailUpdated)
        }
    }
}


// In AccountCreationVC
class AccountCreationVC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "onEmailUpdated", name: EmailUpdated, object: nil)
    }

    func onSubmit() {
        AccountManager.instance.updateEmail("foo@example.com").then { _ -> Void in
            // Success
        }
    }

    @objc func onEmailUpdated() {
        // I don't want this to be called when the event is published following an action
        // in this VC. Though I'm interested in updating this VC whenever the event is fired from
        // other parts of my app.
    }
}

How do I make sure that onEmailUpdated doesn't get events from AccountManager when it calls updateEmail directly? Is there a common pattern to do this?

Here are a couple solutions that I find cumbersome:

  • Don't return a promise in AccountManager.updateEmail, force callers to subscribe to EmailUpdated. I don't like this because you lose context of the call, and it makes it very difficult to chain calls.
  • Unsubscribe from EmailUpdated in AccountCreationVC before the call, and re-subscribe after it completes. Quite hacky.

Aucun commentaire:

Enregistrer un commentaire