KVO、通知、代理、block
KVO: 监听对象属性的变化
1⃣️同步的,所有的监听方法执行会在属性变化的线程上执行,目的是为了保证顺序执行(属性改变后只有先执行完响应的代码才能执行改变属性的下一条语句),因为同步,所以不能线程间通信
2⃣️如果多个线程同时修改一个属性,有可能会出现资源抢夺的问题(加上互斥锁《线程同步》)
// 互斥锁的参数必须是一个对象,任意一个对象都可以,但是不能是线程执行方法中定义的对象,一般用self即可
// // 每次进来之后都会创建一个objLock,默认是打开的,所以加跟没加都是一样的,都是打开的,都能进去
// NSObject *objLock = [[NSObject alloc]init];
// @synchronized(objLock){
// 每一个对象(NSObject)内部都有一个锁(变量),当有线程要进入synchronized到代码块中会先检查对象的锁是打开还是关闭状态,默认锁是打开状态(1),如果是线程执行到代码块内部会先上锁(0)。如果锁被关闭,再有线程要执行代码块就先等待,直到锁打开才可以进去
// 这样就可以了 因为是同一把锁
@synchronized(self.objLock){
// @synchronized(self){
if (self.tickets > 0) {
self.tickets -- ;
NSLog(@"%d--%@",self.tickets,[NSThread currentThread]);
continue;
}
}
3⃣️如果监听的属性非常多,KVO的观察方法将非常难写
4⃣️不用时要记得销毁,且先添加后销毁否则崩溃
🈚️主要用于MVC中视图与模型的同步,当model对象改变时,视图应该随之改变
6⃣️OC用run time机制来实现KVO 当我们第一次观察某个对象的属性时,run time会创建一个新的继承自这个对象的类的子类,在这个子类中,它会重写所有被观察的属性的setter方法,然后将对象的isa指针指向新创建的子类
通知:
1⃣️可以是用户发出,也可以是系统发出,但是统一由兄台那个处理
2⃣️defaultCenter 消息中心只有一个,通过类方法获取它的单例
3⃣️同步的,在发送通知所在的线程执行
4⃣️一定要记着销毁(dealloc)
代理:把某个对象要做的事委托给别的对象去做,那么别的对象就是这个对象的代理,代替它来打理要做的事
1⃣️一对一
2⃣️控制器之间传值
block:提前准备好的一段代码,在需要的时候调用
1⃣️解决循环引用,一半是在block代码中使用了self MRC:_block ARC:_weak
2⃣️block存储位置:
①代码区 没有访问block的外部变量
②栈区 访问外部变量 其实block本质上是一个结构体,结构体存储在栈上
③堆区 实际上放在栈区,ARC情况下自动copy到堆区,MRC情况下存放在栈区,所以函数执行完就会释放,想在外边调用需要copy,这样就copy到堆区
strong,assign属性会出现野指针错误(程序崩溃),释放之后栈地址不会变
总结:
1⃣️方法多时用代理
2⃣️block和代理直接调用方法,效率高一点 通知基于KVO
3⃣️如果想要双向交互就用代理、block,不能用通知