美文网首页iOS开发专题
传值/消息传递机制

传值/消息传递机制

作者: SvenLearn | 来源:发表于2016-06-05 12:04 被阅读153次

    总结

    区别和联系:

    • 映射关系 - Delegate通常是一对一(不提倡一对多来用代理);

    KVC&KVO - 驾驭动态特性并简化代码(KVO会有一定的性能代价)

    观察者模式

    • 推:NSNotificationCenter和KVO - 更方便,将所有状态更新一起打包发给观察者们
    • 拉:delegate - 更灵活,根据需要拉取自己需要的状态

    参考:
    使用UIDocumentInteractionController预览和打开文档
    iOS设计模式之观察者模式


    消息机制摘要

    1. KVO

    "适用前提":
     1. `addObserver:` => 接收者需要知道发送者
     2. `removeObserver:` => 接收者需要知道发送者的生命周期
    
    "关系": 
    
    KVO实现原理 - isa swizzling
    '常见场景'
    1. "逆向传值":比如设置城市,将选择的城市通过代理传回给需要结果的页面(通常是上一个页面)
    2. "事件监听":委托对象监听对象主体的某些重要事件,对事件做出具体响应或广播事件交给需要作出响应的对象;
        比如"UITableViewDelegate"的didSelectRowAtIndexPath:等消息、"UIActionSheetDelegate"的clickedButtonAtIndex:。
    
    '总结'
    一般情形是A委托B去处理一个or一系列的任务,任务达到checkpoint时将当前任务的状态(**值or事件**)
    通过delegate属性通知委托者:"我完成了部分委托任务,你快来决定是否要处理这个任务(值or事件)”。
    
    '关注点'
    尽量使用 `should`、`will`、`did` 动词定义协议的方法
    

    4. Block

    '概念理解'
    只是把常见的方法实现换了一种写法;类似于 内联函数 or 闭包;
    使用block可以减少代码分离,提高代码可读性
    
    '使用 typedef 提高可读性'
    return_type (^block_name)(parameters)
    
    '3种类型和内存管理方式'
        _NSConcreteGlobalBlock   全局的静态 block,不会访问任何外部变量。
        _NSConcreteStackBlock    保存在栈中的 block,当函数返回时会被销毁。
        _NSConcreteMallocBlock   保存在堆中的 block,当引用计数为 0 时会被销毁。
    
    '给block传值的方式'
     1. __block关键字
     2. 使用实例变量
     3. 静态变量 | 静态全局变量 | 全局变量
    其他被截获的自动变量(局部变量)将不能被修改
    
    '实现原理'
    block本质上是一个对象(有isa指针),会把捕获的变量(或其地址[`__block`])拷贝到variables字段中;
    block的调用则通过FuncPtr字段的函数指针执行。
    
    '最佳实践'
    总是在ARC下使用block,否则需要注意block是在stack中还是heap中!!!
    
    "风险"
    retain环 => "解决方案":nil 或 __weak
    

    传送门:
    Objective-C Blocks Quiz
    谈Objective-C block的实现
    内联函数定义

    5. Target-Action

    "适用场景" => 处理不带参数的UI事件(默认的sender除外)
    
    "局限" => 不能携带自定义的信息
    

    消息机制的选择

    交互模式决策流程图
    举例
    1. 发送者 - NSOperation;接收者 - NSOperationQueue;消息:isFinished,isExecuting,isCancelled
    不是无负载的UI事件 => 发送者知道接收者 => 不是双向通信 => 只关心值变化且发送者是KVO兼容的 => "KVO"
    
    1. 发送者 - NSManagedObjectContext;接收者 - 未知;消息:NS……ObjectsDidChangeNotification
    不是无负载的UI事件 => 发送者不知道接收者 => "可能有多个接收者" => "NSNotification"
    
    1. 发送者 - UITableViewDelegate;接收者 - UITableView;消息:tableView:didSelectRowAtIndexPath:
    不是"无负载"的UI事件 => 发送者知道接收者 => 不是双向通信 => 不只关心值变化 => 没有多个接收者 
    => "消息不是回调/方法调用" => "Delegate"
    
    1. 发送者 - NSURLSession;接收者 - 某个对象;消息:completionHandler
    不是"无负载"的UI事件 => 发送者知道接收者 => 不是双向通信 => 不只关心值变化 => 没有多个接收者 
    => "消息是方法的调用" => 发送者能确保回调block的nil设置 => "Block"
    
    1. 发送者 - UIButton;接收者 - VC;消息:UIEvent
    无额外负载的UI事件 => "Target-Action"
    

    拓展:观察者模式

    NSNotificationCenter

    考虑到效率、block支持、扩展性,可以考虑使用第三方库DZNotificationCenter

    KVO

    考虑到block支持、及时移除、线程安全,可以考虑使用第三方类库KVOController


    可以使用代理delegate来实现拉模型:收到更新时,delegate执行protocol的方法获取最新状态

    拓展:KVC

    通过集合代理对象模拟属性来实现 KVC,需要实现的方法:


    不可变容器

    集合代理对象被修改时需要实现的方法:


    可变容器

    相关文章

      网友评论

        本文标题:传值/消息传递机制

        本文链接:https://www.haomeiwen.com/subject/hfaarttx.html