一、基本描述
- readwrite:读写权限:readonly,readwrite(默认)
- readonly: 是只读属性,只会生产getter方法,不会生产setter方法;
- assign:修饰基本数据类型,修饰对象类型时,不改变其引用计数,会产生悬垂指针,修饰的对象在被释放后,assign指针仍然指向原对象内存地址,如果使用assign指针继续访问原对象的话,就可能会导致内存泄漏或程序异常。
- retain:表示持有特性,setter方法将传入参数先保留再赋值,传入参数的引用计数会+1;
- copy:分为深拷贝和浅拷贝,浅拷贝:对内存地址的复制,让目标对象指针和原对象指向同一片内存空间会增加引用计数,深拷贝:对对象内容的复制,开辟新的内存空间.可变对象的copy和mutableCopy都是深拷贝,不可变对象的copy是浅拷贝,mutableCopy是深拷贝,copy方法返回的都是不可变对象.
- atomic:nonatomic。原子性和非原子性的内部实现区别只是atomic对象setter和getter方法会加一个锁,而nonatomic并没有。原子性保证了读写线程安全,在多线程中,无论怎么操作对象的setter方法都能通过getter方法获得完整的数据,但是获得到的数据是否是想要的就不确定了,如果想要保证线程安全需要通过上锁或其他方式保证线程安全。
- weak:不改变被修饰对象的引用计数,所指对象在被释放后,weak指针会自动置为nil
二、相关问题
1.weak和assign区别?
- 修饰变量类型的区别。weak 只可以修饰对象。如果修饰基本数据类型,编译器会报错-“Property with ‘weak’ attribute must be of object type”。
assign 可修饰对象,和基本数据类型。当需要修饰对象类型时,MRC时代使用unsafe_unretained。当然,unsafe_unretained也可能产生野指针,所以它名字是"unsafe_”。 - 是否产生野指针的区别。weak 不会产生野指针问题。因为weak修饰的对象释放后,指针会自动被置nil,之后再向该对象发消息也不会崩溃。 weak是安全的。
assign 如果修饰对象,会产生野指针问题;如果修饰基本数据类型则是安全的。修饰的对象释放后,指针不会自动被置空,此时向对象发消息会崩溃。
- weak实现流程
1 初始化时:runtime会调用objc_initWeak函数,objc_initWeak函数会初始化一个新的weak指针指向对象的地址。
2 添加引用时:objc_initWeak函数会调用 objc_storeWeak() 函数, objc_storeWeak() 的作用是更新指针指向,创建对应的弱引用表。
3 释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。
- 为什么代理不能使用assign
修饰的对象释放后,指针不会自动被置空,此时向对象发消息会崩溃。
网友评论