iOS ARC下 weak 和 assign 的区别

一、相似

1.都可以修饰对象类型,但是assign修饰对象会存在问题。

2.都是弱引用类,不能保住 OC 对象的生命。

二、区别

1.修饰变量类型的区别

weak 只可以修饰对象。如果修饰基本数据类型,编译器会报错-“Property with ‘weak’ attribute must be of object type”。

assign 可修饰对象和基本数据类型。

2.是否产生野指针

weak 指向的对象销毁时,会将当前指向对象的指针指向nil,防止野指针的生成。

assign 指向的对象销毁时,不会将当前指向对象的指针指向nil,有野指针的生成。


iOS ARC下 weak 和 assign 的区别_第1张图片
iOS ARC下 weak 和 assign 的区别_第2张图片
iOS ARC下 weak 和 assign 的区别_第3张图片

生成用 assign、weak、strong 修饰的三个变量:assignPoint、weakPonit、strongPoint;

将 self.strongPoint 赋值给 self.weakPoint 和 self.assignPoint ,然后释放 self.strongPoint ,那么相应的 self.weakPoint 指向的对象就会释放,self.weakPoint 也会将值设置为nil。

而 self.assignPoint 中的引用虽然释放了,但是值却还是原来 self.strongPoint 中的值,所以当引用的时候就会造成野指针。


Runtime 如何实现 weak 变量的自动置nil?

Runtime 对注册的类, 会进行布局,对于 weak 对象会放入一个 hash 表中。 用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会 dealloc,假如 weak 指向的对象内存地址是a,那么就会以a为键, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。

Runtime 如何实现 weak 属性具体流程大致分为 3 步:

1、初始化时:runtime 会调用 objc_initWeak 函数,初始化一个新的 weak 指针指向对象的地址。

2、添加引用时:objc_initWeak 函数会调用 objc_storeWeak() 函数,objc_storeWeak() 的作用是更新指针指向(指针可能原来指向着其他对象,这时候需要将该 weak 指针与旧对象解除绑定,会调用到 weak_unregister_no_lock),如果指针指向的新对象非空,则创建对应的弱引用表,将 weak 指针与新对象进行绑定,会调用到 weak_register_no_lock。在这个过程中,为了防止多线程中竞争冲突,会有一些锁的操作。

3、释放时:调用 clearDeallocating 函数,clearDeallocating 函数首先根据对象地址获取所有 weak 指针地址的数组,然后遍历这个数组把其中的数据设为 nil,最后把这个 entry 从 weak 表中删除,最后清理对象的记录。


你可能感兴趣的:(iOS ARC下 weak 和 assign 的区别)