6.iOS消息传递的方式

1.KVC实现原理

  • KVC, 键-值编码,使用字符串直接访问对象属性.
  • 底层实现, 当一个对象调用setValue方法时, 方法内部会实现以下操作:
    1.检查是否存在相对应的key的set方法, 如果存在, 就调用set方法
    2.如果set方法不存在, 就会查找与key相同名称并且带下划线的成员属性, 如果有,则直接给成员属性赋值
    3.如果没找到_key, 就会查找相同名称的属性key,如果有就直接赋值
    4.如果还没有找到, 则调用valueForUndefinedKey: 和setValue: forUnderfinedKey: 方法
    

2.KVO的实现原理

image
KVO-简直观察机制,原理如下:
  • 1.当给A类添加KVO的时候, runtime动态的生成一个子类NSKVONotifying_A, 让A类的isa指针指向 NSKVONotifying_A类, 重写class方法, 隐藏对象真实类信息
  • 2.重写监听属性的setter方法, 在setter方法内部调用了Foundation的_NSSetObjectValueAndNotofy函数
  • 3._NSSetObjectValueAndNotofy函数内部
    3.1. 首先会调用willChangeValueForKey
    3.2. 然后给属性赋值
    3.3. 最后调用didChangeValueForKey
    3.4. 再调用observer的observeValueForKeyPath去告诉监听器属性值发生了变化
    
  • 4.重写了dalloc做一些KVO内存释放操作

3.如何手动触发KVO方法

  • 手动调用willChangeValueForKey和didChangeValueForKey方法
  • 键值观察通知依赖于NSObject的两个方法:willChangeValueForKey:和didChangeValueForKey.在一个被观察属性发生变化之前, willChangeValueForKey:一定会被调用, 这就会记录旧的值. 而当改变发生后,didChangeValueForKey会被调用, 继而observeValueForKey: ofObject:change:context:也会被调用. 如果可以手动实现这些调用,就可以实现"手动触发"了 ,如果只调用didChangeValueForKey方法是不可以触发KVO方法的, 因为willChangeValueForKey:记录旧的值, 如果不记录旧的值, 那就没有改变一说了

4.通知和代理有什么区别

  • 通知是观察者模式, 适合一对多的场景
  • 代理模式适合一对一的反向传值
  • 通知耦合度低,代理耦合度高

5.block和delegate的区别

  • delegate运行成本低, block的运行成本高
    block出栈需要将使用的数据从栈内存拷贝到堆内存,当然对象的话就是引用计数加一,使用完或者block置nil后才消除. delegate只是保存了一个对象的指针, 直接回调, 没有额外消耗. 就像C语言的函数指针, 只多做了一个查表动作.
  • delegate更适用于多个回调方法(一般3个以上), block则适用于1,2个回调的时候.

6.为什么block用copy关键字

block在没有使用外部变量时, 内存存在全局区, 然而 ,当block在使用外部变量的时候, 内存是存在于栈区, 当block copy之后, 是存在于堆区的. 存在于栈区的特点是对象随时可能销毁, 一旦销毁在回调的时候, 就会出现系统崩溃, 所以block要使用关键字copy.

你可能感兴趣的:(6.iOS消息传递的方式)