传值/消息传递机制

总结

区别和联系:

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

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

观察者模式

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

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


消息机制摘要

1. KVO

"适用前提":
 1. `addObserver:` => 接收者需要知道发送者
 2. `removeObserver:` => 接收者需要知道发送者的生命周期
"关系": 
KVO实现原理 - isa swizzling

2. 通知

"适用场景" => 在代码中的两个不相关的模块中传递消息
"原理简析":经典的推送型观察者模式
"常见的系统通知"
UIDevice通知 - UIDevice[Orientation|BatteryState|BatteryLevel|ProximityState]DidChangeNotification
键盘通知 - Show | Hide | ChangeFrame
"最佳实践":
通知的发送和处理必须在同一个线程中。
尽可能迟地去注册一个观察者,并尽可能早将其移除。

3. 协议代理

"适用场景": 发送者需要知道接收者 => 在相对接近的两个模块间传递消息

使用惯例

'常见场景'
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,需要实现的方法:


不可变容器

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


可变容器
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,121评论 29 470
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 设计模式 1.delegate和notification什么区别,什么情况使用? 2.描述一下KVO和KVC。 K...
    丶逐渐阅读 1,946评论 3 2
  • 消息传递机制 分类 在一个应用中不同的对象之间需要通过相互传递消息的方式结合起来共同完成任务。iOS 中主要的消息...
    水止云起阅读 483评论 0 2
  • 每个应用或多或少都由一些需要相互传递消息的对象结合起来以完成任务。在这篇文章里,我们将介绍所有可用的消息传递机制,...
    爱敲代码的果果阅读 3,927评论 0 2