壹:@property的内存管理策略
@property 的本质:
@property = ivar + getter + setter;
“属性” (property)有两大概念:ivar(实例变量)、存取方法(access method = getter + setter)。
我们都知道, @property修饰符, 系统会给类声明的属性声明默认 (最简单的) 的setter和getter方法.
一般它有如下四个作用:
1.控制set方法的内存管理
①MRC下, @property的内存管理策略:
- retain : release旧值,retain新值(用于OC对象)
- assign :直接赋值,不做任何内存管理 (默认,用于非OC对象类型)
- copy : release旧值,copy新值(一般用于NSString *和block)
②ARC下, @property的内存管理策略 (重点掌握) :
- copy : NSString *和block对象
- strong : 除NSString\block以外的OC对象, 强指针引用过, 防止对象被销毁
- weak : 当两个对象互相引用时, 一端用strong, 一端用weak, 防止循环引用
- assign : 基本数据类型
2.控制需不需要生成set方法
- readwrite :同时生成set方法和get方法(默认)
- readonly :只会生成get方法
3.多线程管理
- atomic :线程安全,性能低,并不能完全保证安全(默认)
- nonatomic :线程不安全,性能高
4.控制set方法和get方法的名称
- setter : 设置set方法的名称,一定有个冒号:
- getter : 设置get方法的名称
贰:Copy属性修饰符解惑
困惑1: 为什么我们要用copy修饰NSString对象?
如果我们查阅资料, 会发现很多答案, (copy方法和深浅复制的使用在我之前的一篇文章讲到了, 如果还不太理解可以点击)
那么其实在@property中使用copy修饰符就是为了防止NSMutableString赋值给NSString(也就是我们的成员属性)时, 前者的修改引起了后者的值变化.
copy方法底层, 会在setString:这个方法内做判断:
如果赋值来源是NSString时, copy的作用和strong作用相同, 只是起了强引用的作用(因为NSString对象本身是不可被修改的);
如果赋值来源是NSMutableString时, copy会对其做深拷贝, 生成一个新的对象, 那么我们修改赋值来源的对象时,我们的成员属性就不会因为来源的值改变而改变了!
困惑2: 为什么我们要用copy修饰block对象?
简单来说,block就像一个函数指针,指向我们要使用的函数。
就和函数调用一样的,不管你在哪里写了这个block,只要你把它放在了内存中(通过调用存在这个block的方法或者是函数),不管放在栈中、堆中,还是在静态区,只要该block没有被销毁,你都可以用“blockName()”调用他。
说到在类中声明一个block为什么要用copy修饰的话,那就要先说block的三种类型。
1._NSConcreteGlobalBlock,全局的静态block,不会访问外部的变量。
就是说如果你的block没有调用其他的外部变量,那你的block类型就是这种。
例如:你仅仅在你的block里面写一个NSLog(“hello world”);2._NSConcreteStackBlock,保存在栈中的 block,当函数返回时会被销毁。
这个block就是你声明的时候不用copy修饰,并且你的block访问了外部变量。3._NSConcreteMallocBlock,保存在堆中的 block,当引用计数为 0 时会被销毁。
好了,这个就是今天的主角 ,用copy修饰的block。
我们知道,函数的声明周期是随着函数调用的结束就终止了。我们的block是写在函数中的。
如果是全局静态block的话,他直到程序结束的时候,才会被被释放。但是我们实际操作中基本上不会使用到不访问外部变量的block。
如果是保存在栈中的block,他会随着函数调用结束被销毁。从而导致我们在执行一个包含block的函数之后,就无法再访问这个block。因为(函数结束,函数栈就销毁了,存在函数里面的block也就没有了),我们再使用block时,就会产生空指针异常。
如果是堆中的block,也就是copy修饰的block。他的生命周期就是随着对象的销毁而结束的。只要对象不销毁,我们就可以调用的到在堆中的block。
这就是为什么我们要用copy来修饰block。因为不用copy修饰的访问外部变量的block,只在他所在的函数被调用的那一瞬间可以使用。之后就消失了。

@property不仅涉及实例变量和存取方法,还包括内存管理策略。本文详细解析了MRC和ARC下的内存管理,如retain、assign、copy等。在NSString和block对象上使用copy修饰符的原因是为了确保数据的稳定性和避免生命周期问题。对于NSString,copy能防止NSMutableString的修改影响到NSString。而对于block,copy能将栈上的_block转化为堆上的_NSConcreteMallocBlock,延长其生命周期,确保在对象存活期间可以正常使用。
3894

被折叠的 条评论
为什么被折叠?



