第一种情况: 使用 copy 修饰
// 代码片段1
// Person.h
@interface Person : NSObject
@property (nonatomic, copy) NSString *lastName;
@end
// Person.m
@implementation Person
- (instancetype)init {
self = [super init];
if (self) {
_lastName = @"name";
}
return self;
}
@end
// main.m
int main(int argc, const char * argv[]) {
Person *p1 = [[Person alloc] init];
NSLog(@"lastname = %@, lastname address = %p", p1.lastName, p1.lastName);
NSMutableString *newLastName = [[NSMutableString alloc] initWithString:@"newname"];
NSLog(@"newLastName = %@, newLastName address = %p", newLastName, newLastName);
p1.lastName = newLastName;
NSLog(@"lastname = %@, lastname address = %p", p1.lastName, p1.lastName);
return 0;
}
以上代码执行后的结果如下:
lastname = name, lastname address = 0x100001078
newLastName = newname, newLastName address = 0x1003031e0
lastname = newname, lastname address = 0x100303720
从以上打印的结果可以看到,第一次打印的 lastname address
和第二次打印的 lastname address
结果并不相同,同时 newLastName address
和第二次打印的 lastname address
也不相同,说明执行 p1.lastName = newLastName
之后 p1.lastName
指向了一块全新的内存空间,这就是 copy
的作用:重新开辟一块内存空间存放 newLastName
的值。
改变一: 修改 main
方法中的代码,在 return 0
之前添加以下代码
[newLastName appendString:@"abc"];
NSLog(@"lastname = %@, lastname address = %p", p1.lastName, p1.lastName);
newLastName
的值变成了 newnameabc
,但是 p1.lastName
的值没有任何变化。这很简单,根据 copy
的作用 p1.lastName
和 newLastName
指向完全不同的地址,对 newLastName
做的改变自然不会反映在 p1.lastName
上。
第二种情况: 使用 strong 修饰
将代码:
@property (nonatomic, copy) NSString *lastName;
修改为:
@property (nonatomic, strong) NSString *lastName;
执行代码片段1之后的结果如下:
lastname = name, lastname address = 0x100001068
newLastName = newname, newLastName address = 0x100202e00
lastname = newname, lastname address = 0x100202e00
从以上结果中发现第一次打印的 lastname address
和第二次打印的 lastname address
指向不同的内存,但是第二次打印的 lastname address
和 newLastName address
相同,说明,与 copy
不同的是,strong
并没有开辟一块新的内存空间,而是直接将 lastname
指向了 newLastName
。
改变一: 修改 main
方法中的代码,在 return 0
之前添加以下代码
[newLastName appendString:@"abc"];
NSLog(@"newLastName = %@, newLastName address = %p", newLastName, newLastName);
NSLog(@"lastname = %@, lastname address = %p", p1.lastName, p1.lastName);
打印结果如下:
newLastName = newnameabc, newLastName address = 0x100202e00
lastname = newnameabc, lastname address = 0x100202e00
因为 newLastName
和 p1.lastname
指向同一个内存,对 newLastName
的改变也就改变了 p1.lastname
。但是 lastname
属性是不可变的 NSString
类型,而在这里却发生了改变。
另外
如果有以下代码:
@property (nonatomic, copy) NSMutableString *mString;
如果在未来给 mString
重新赋了一个新值,则会产生一个不可变的副本,此时想在 mString
上调用 NSMutableString
的相关方法是不行的。
结论
用 copy
修饰的 NSString
如果在无意中被一个 NSMutableString
类型的变量赋值,原先的 NSString
会被 copy
一份用来存储 NSMutableString
的值,万一 NSMutableString
的值被修改,不会影响到 NSString
的值,这能体现 NSString
作为不可变类型的性质。
用 strong
修饰的 NSString
如果在无意中被一个 NSMutableString
类型的变量赋值, NSString
不会被拷贝,一旦 NSMutableString
的值被修改,NSString
的值也就发生了改变,这与 NSString
作为不可变类型相违背。
当然如果 NSString
被一个 NSString
赋值,copy
的效果与 strong
的效果是一样的,直接改了就是。
以上的结论同样适用于 NSArray
和 NSDictionary
。