7

Would like to have your opinion regarding the following architecture:

In My app I have a static class (LoginManager) that handles an asynchronous login. Once the login phase is completed the app should response and transition to another state.

I have 2 implementation suggestions

  1. using a Delegate:

    import Foundation
    
    protocol LoginManagerDelegate{
        func onLogin(result:AnyObject)
    }
    
    class LoginManager {
        struct Wrapper {
            static var delegate:LoginManagerDelegate?
        }
    
        class func userDidLogin(result){            
             Wrapper.delegate?.onLogin(result)
        }
    
    }
    
  2. using a Notification:

    import Foundation
    
    class LoginManager {
    
        class func userDidLogin(result){            
             NSNotificationCenter.defaultCenter().postNotificationName("onLogin", object: result)
        }
    
    }
    

Q:What would be the best approach?

Shlomi Schwartz
  • 8,693
  • 29
  • 109
  • 186

4 Answers4

11

For

  1. Delegate/Protocol

It is generally used when you want to update or done any procedure in you previous controller from current view controller. so if you want to update values in previous view controller then Delegate/Protocol is preferable.

So it is basically 1-to-1 Relation.

  1. Notification

It is generally used when you want to update values in your view controller from any other viewcontroller. so its basically 1-to-n relation.

So use this type as per your requirement.

Maybe this will help you.

ChintaN -Maddy- Ramani
  • 5,156
  • 1
  • 27
  • 48
9

If the

func onLogin(result:AnyObject)

Is implemented in only one class, I would go with the delegate. More appropriate for a 1 to 1 relation.

If it's an 1 to n relation, I would go with the Notification.

I don't like to rely on Notification (personal taste), so I usually handle the login/logout transitions in my AppDelegate, which permits me to use the Delegate pattern.

Mehdi.Sqalli
  • 510
  • 1
  • 5
  • 22
1

3: A callback function. (like 1, but without the faff of declaring a protocol specifically just for this purpose).

class LoginManager {
    // using this singleton makes me feel dirty
    struct Wrapper {
        // this AnyObject too...
        static var callback: ((result: AnyObject)->())?
    }

    class func userDidLogin(result){            
         Wrapper.callback?(result)
    }
}
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • thanks for the reply. why don't you like the singleton approach? – Shlomi Schwartz Dec 25 '14 at 13:11
  • Global state can be troublesome and best avoided if practical. The fact you have to make it an optional is a sign there might be a better way. Say you re-used the login class but forgot to set the callback–could cause a nasty bug. Do you have the thing you want to call back to-hand when you create the login object? In which case you could just pass it in as a parameter and make it a regular member property (and ditch the optional, maybe make it a `let` not a `var`). Similarly, why use `AnyObject`? You know what type you’re planning to pass into the callback argument, make it that type. HTH. – Airspeed Velocity Dec 25 '14 at 14:13
  • for full disclosure, I'm using facebook as the 3rd party login authenticator, the AnyObject is the result I get back for the startForMeWithCompletionHandler method. "Say you re-used the login class but forgot to set the callback–could cause a nasty bug" that is why I thought about a delegate. could you please provide an alternative approach that will keep the login mechanism decoupled from the main logic? – Shlomi Schwartz Dec 25 '14 at 14:52
  • The delegate doesn’t really help mitigate the risk of the global state. Basically, using your `LoginManager` is a multi-step process. First you have to set the callback. Then display the manager to receive a callback. If you forget to do the first one, weird stuff happens. `LoginManager` isn’t really a “class” – it’s a global variable and a global function. If you instead made `LoginManager` a thing you create, you could give it an `init` that took the callback. – Airspeed Velocity Dec 25 '14 at 16:15
0

I would go for completion block with delegate implemented. By the way, as a good practice, NSNotification should not be fired/used for transition. Better use delegates.

Bizcharts
  • 44
  • 2