copy
建立一个索引数为一的对象,然后释放旧对象。
- NSString、NSArray、NSDictionary 等经常使用copy关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,为了保证在使用过程中不会被修改,使用 copy 复制出新的对象。
assgin
简单赋值,不更改索引计数。
- 适用于基本数据类型:NSInteger、BOOL、CGFloat等
strong
ARC 下默认模式,释放旧对象,引用新对象,并使新对象的计数器加一。使用绝大部分 NSObject 对象。
weak
引用新对象,该对象的计数器不加一。
- 在ARC模式下,解决循环引用导致内存泄漏的问题,使用weak关键字
- 自身已经对它进行了一次强引用,没有必要再强引用的时候,使用weak关键字
readonly
表示这个属性是只读的,只生成getter方法,不会生成setter方法。
readwrite
可读可写(默认)设置可访问级别,ARC 下默认修饰符。
retain
MRC 下的 strong
,释放(release)旧对象,引用新对象,并使新对象的计数器加一。
nonatomic
非原子性访问,不加同步,多线程并发访问会提高性能。
atomic
原子性访问,最属性的 setter
和 getter
进行加锁操作以保证值的完整性。
扩展
为什么NSString、NSDictionary、NSArray要使用copy修饰符呢?
要搞清楚这个问题,我们先来弄明白深拷贝与浅拷贝的区别,以非集合类与集合类两种情况来进行说明下,先看非集合类的情况,代码如下:
NSString *name = @"LOLITA";
NSString *newName = name.copy;
NSLog(@"name address:%p ---- newName address:%p",name,newName);
输出信息如下:
name address:0x1000d0520 ---- newName address:0x1000d0520
可以看出复制过后,内存地址是一样的,没有发生变化,这就是浅拷贝,只是把指针的地址复制了一份;
我们修改代码为name.mutableCopy,此时输出的信息图下:
name address:0x1000f4520 ---- newName address:0x17426fb40
此时内存地址发生了变化,并且newName的内存地址的偏移量比name的内存地址大许多,由此可见name经过mutableCopy操作之后,被复制到新的区域了,这就是深拷贝,深拷贝不仅拷贝地址还拷贝了内容。
上面的都是不可变对象,在看下可变对象的情况,代码如下:
NSMutableString *name = [[NSMutableString alloc] initWithString:@"LOLITA"];
NSMutableString *newName = name.copy;
NSLog(@"name address:%p ---- newName address:%p",name,newName);
输出信息如下:
name address:0x17026cdc0 ---- newName address:0xa004154494c4f4c6
从上面可以看出copy之后,内存地址不一样,这是深复制,内容也就进行拷贝。在把代码改成name.mutableCopy,此时日志的输出信息如下:
name address:0x17007a380 ---- newName address:0x17007d6c0
可以看出可变对象copy与mutableCopy的效果是一样的,都是深拷贝。
总结:对于非集合类对象的copy操作如下:
-
[immutableObject copy]; // 浅拷贝
-
[immutableObject mutableCopy]; // 深拷贝
-
[mutableObject copy]; // 深拷贝
-
[mutableObject mutableCopy]; // 深拷贝
采用同样的方法可以验证集合类对象的copy操作如下:
-
[immutableObject copy]; // 浅拷贝
-
[immutableObject mutableCopy]; // 单层深拷贝
-
[mutableObject copy]; // 深拷贝
-
[mutableObject mutableCopy]; // 深拷贝
对于NSString、NSDictionary、NSArray等经常使用copy关键字,是因为它们有对应的可变类型:NSMutableString、NSMutableDictionary、NSMutableArray,它们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性时拷贝一份。
strong 和 copy 修饰区别**
分别使用两种修饰符来修饰NSArray
@property (copy ,nonatomic) NSArray *bookArray1;
@property (strong ,nonatomic) NSArray *bookArray2;
NSMutableArray *books = [NSMutableArray arrayWithObject:@"book1"];
self.bookArray1 = books;
self.bookArray2 = books;
[books addObject:@"book2"]; // 当数组改变时
NSLog(@"bookArray1:%@",self.bookArray1);
NSLog(@"bookArray2:%@",self.bookArray2);
输出结果:
bookArray1:(
book1
)
bookArray2:(
book1,
book2
)
由此可以看出,books 被改变时,strong 修饰的 bookArray2 也随之改变。
这说明strong对books进行浅拷贝,只拷贝了指针,books 和 bookArray2 指向同一个地址,内容是一样的。
而copy对books进行了深拷贝,是针对内容进行了拷贝,所以books的改变不会影响到bookArray1。