property中的属性关键字

本文详细解析了在ARC环境下,Objective-C默认属性关键字的作用与区别,包括atomic与nonatomic、readwrite与readonly、strong与weak、assign与weak,以及copy与retain的特性,帮助开发者深入理解并合理使用这些关键字。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?

atomicreadwritestrong(对象)、assgin(基本数据类型)。

具体比较分析:

1、atomic与nonatomic

atomic:默认是有该属性的,这个属性是为了保证程序在多线程情况下,编译器会自动生成一些加锁代码,避免该变量的读写不同步的问题,提供多线程安全。

nonatomic:如果该对象无需考虑多线程的情况,加入这个属性,这样会让编译器少生成一些加锁代码,禁止多线程,变量保护,提高性能和效率。

注:atomic是Objc使用的一种线程保护技术,基本上来讲是防止在写未完成的时候另一个线程读取,造成的数据错误。而这种机制是非常耗费系统资源的,所以iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。而iOS开发中,普遍使用nonatomic也是基于性能这一点。

扩展:

自旋锁和互斥锁

共同点: 都可以锁定一段代码。同一时间,只有线程能够执行这段锁定的代码。

区别:互斥锁,在锁定的时候,其他线程会睡眠,等待条件满足,再唤醒。

自旋锁,在锁定的时候,其他的线程会做死循环,一直等待这条件满足,一旦条件满足,立马去执行,少了一个唤醒过程。

2、readwrite与readonly

readwrite:这个属性是默认的情况,会自动为你生成存取器。

readonly:只生成getter,不会生成setter方法。

注:

readwrite、readonly这两个属性的真正价值,不是提供成员变量的访问接口,而是控制成员变量的访问权限。

3、strong与weak

strong:强引用,也是我们通常说的引用,其存亡直接决定了所指向对象的存亡,当强引用指向了某个对象,那便拥有了这个对象。如果不存在指向一个对象的引用,并且此对象不再使用,则对象就会被从内存中释放掉。默认所有实例变量和局部变量都是strong指针。

weak:弱引用,不决定对象的存亡,只是单纯的引用了某个对象但是并不拥有该对象。即使一个对象被持有无数个弱引用,只要没有强引用指向它,那么还是会被清除。

注:

strong与retain功能相似;weak与assign相似,只是当对象消失后weak会自动把指针置为nil,避免了野指针的产生,因而weak属性就不需要在dealloc中置nil了。

4、assign和weak

weak 此特质表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同assign类似, 然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。 而 assign 的“设置方法”只会执行针对“纯量类型” (scalar type,例如 CGFloat 或 NSlnteger 等)的简单赋值操作。

 weak 必须用于 OC 对象,而assign 可以用非 OC 对象。

使用assign: 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等)

注:

1.修饰变量类型的区别

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

assign可修饰对象,和基本数据类型。当需要修饰对象类型时,MRC时代使用unsafe_unretained。当然,unsafe_unretained也可能产生野指针,所以它名字是"unsafe_”。

2.是否产生野指针的区别

weak不会产生野指针问题。因为weak修饰的对象释放后(引用计数器值为0),指针会自动被置nil,之后再向该对象发消息也不会崩溃。 weak是安全的。

assign如果修饰对象,会产生野指针问题;如果修饰基本数据类型则是安全的。修饰的对象释放后,指针不会自动被置空,此时向对象发消息会崩溃。

assign适用于基本数据类型如int,float,struct等值类型,不适用于引用类型。因为值类型会被放入栈中,遵循先进后出原则,由系统负责管理栈内存。而引用类型会被放入堆中,需要我们自己手动管理内存或通过ARC管理。

weak适用于delegate和block等引用类型,不会导致野指针问题,也不会循环引用,非常安全。

5、copy和retain

assgin:默认类型,setter方法直接赋值,不进行任何的retain操作,不改变引用计数。一般用来处理基本数据类型。

retain:释放旧的对象(release),将旧对象的值赋给新对象,再令新对象引用计数为1。可理解为指针拷贝。

copy:与retain的流程一样,先对旧的值release,再copy出新的对象,引用计数为1,为了减少对上下文的依赖而引入的机制。可以理解为内容的拷贝,也就意味着内容被copy后,内存中会有两个存储空间存储同样的内容。

对copy属性要特别注意:被定义有copy属性的对象必须要 符合NSCopying协议,必须实现- (id)copyWithZone:(NSZone *)zone方法。对copy属性要特别注意:被定义有copy属性的对象必须要 符合NSCopying协议,必须实现- (id)copyWithZone:(NSZone *)zone方法。

对于不可变对象来说,copy为浅拷贝,和strong一样,均增加了源对象的引用计数;而对于可变对象来说,copy为深拷贝,我们知道深拷贝为内容拷贝,所以如果改变源对象时,声明成copy的属性并不会跟着变化。而由于声明成strong的属性只是增加源对象的引用计数,依旧指向源对象,故会同步改变。所以,当我们声明属性时,如果不希望它因为源对象(源对象为可变对象时)的改变而改变,则用copy修饰。

扩展

深拷贝与浅拷贝

深拷贝就是内容拷贝,浅拷贝就是指针拷贝

其实copy本质是用来做深拷贝的,但是修饰不可变的数组时,由于深拷贝出来也不能做添加或删除操作,为了节约资源,直接浅拷贝了。

深拷贝就是拷贝出和原来仅仅是值一样,但是内存地址完全不一样的新的对象,创建后和原对象没有任何关系。

浅拷贝就是拷贝指向原来对象的指针,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象。

[immutableObject copy] //浅复制

[immutableObject mutableCopy] //单层深复制

[mutableObject copy] //单层深复制

[mutableObject mutableCopy] //单层深复制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值