iOS - Delegate与Notification的区别

7

我希望了解您对以下架构的看法:

我的应用程序中有一个静态类(LoginManager),用于处理异步登录。一旦登录阶段完成,应用程序应该响应并过渡到另一个状态。

我有两个实现建议:

  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)
        }
    
    }
    

: 最佳方法是什么?

4个回答

11

Delegate/Protocol

Delegate/协议一般用于在当前View Controller中更新或执行之前的Controller的任何过程。如果要在上一个视图控制器中更新值,则最好使用Delegate/协议。

因此,它基本上是1对1的关系。

注意:使用时请保留HTML标记。

  1. Notification

通知一般用于从其他ViewController更新您的ViewController中的值。这是基本上是1对n的关系。

所以根据您的需求选择适当的类型。

希望这可以帮到您。

注意:使用时请保留HTML标记。


9
如果

func onLogin(result:AnyObject)

只在一个类中实现,我会选择使用 委托。这更适合于1对1的关系
如果是1对n的关系,我会选择使用通知
个人不喜欢依赖通知,因此我通常在我的AppDelegate中处理登录/注销转换,这使我可以使用委托模式。

1

3:一个回调函数。(与1相似,但不需要专门声明协议来实现此目的)。

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)
    }
}

谢谢回复。为什么你不喜欢单例模式? - Shlomi Schwartz
全局状态可能会带来麻烦,如果可以的话最好避免使用。你必须将其设置为可选项是一个迹象,表明可能有更好的方式。比如说,你重用了登录类但忘记了设置回调 - 这可能会导致严重的错误。当你创建登录对象时,你是否已经拥有了想要回调的东西?如果是这样,你可以将其作为参数传递并使其成为普通成员属性(丢弃可选项,可能将其作为 let 而不是 var)。同样地,为什么要使用 AnyObject?你知道你计划传递到回调参数中的类型,就将其指定为该类型即可。希望对你有所帮助。 - Airspeed Velocity
为了完全透明,我正在使用Facebook作为第三方登录验证器,AnyObject是我通过startForMeWithCompletionHandler方法得到的结果。“假设您重用了登录类但忘记设置回调 - 可能会导致严重错误”,这就是为什么我考虑使用委托的原因。您能否提供一种替代方法,以使登录机制与主要逻辑解耦? - Shlomi Schwartz
委托并不能真正帮助减轻全局状态的风险。基本上,使用您的 LoginManager 是一个多步骤的过程。首先,您必须设置回调。然后显示管理器以接收回调。如果您忘记了第一个步骤,奇怪的事情就会发生。LoginManager 并不是真正的“类”——它是一个全局变量和全局函数。如果您将 LoginManager 改为您创建的对象,您可以给它一个接受回调的 init - Airspeed Velocity

0
我会选择实现代理的完成块。顺便说一下,作为一个良好的实践,不应该使用NSNotification来进行过渡。 最好使用代理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接