Objective-C之property属性分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ixiaochouyu/article/details/48690453
@property和@synthesize用来生成属性的set和get方法

格式:
@property(属性列表) 类型 属性名
@synthesize 属性名

属性列表包括:strong(retain), copy, weak(assign), atomic, nonatomic, readonly, readwrite, getter=name, setter=name
strong和weak是引入ARC时加入的关键字
属性列表与关键字的对应关系

属性值

关键字

所有权

strong, copy, retain

__strong

weak

__weak

assign, unsafe_unretained

__unsafe_unretained

属性默认为assign(如果属性是NSObject(或者它子类的)的对象时,默认为strong), readwrite, atomic
@property int i;等价于@property(assign, readwrite, atomic) int i;
@property NSString *s;等价于@property(strong, readwrite, atomic) NSString *s;

strong和retain类似,对所指的对象引用计数加1(如果所指对象是可变对象的话)
NSMutableString *str = [[NSMutableString alloc] initWithUTF8String:"mutablestring"];
member.strong = str; // 头文件定义@property(strong) NSString *strong; strong和str指向同一个内存地址
NSLog(@"%ld", CFGetRetainCount((__bridge CFTypeRef)(str))); // 输出2(NSLog可能对引用计数结果有影响,所以在这之前不要使用类似NSLog(@"%@", member.strong);语句,最好在查看引用计数时先屏蔽掉其他NSLog)
NSLog(@"%@", member.strong); // 输出mutablestring
[str deleteCharactersInRange:NSMakeRange(0, 7)];
NSLog(@"%@", member.strong); // 输出string
 
 

我改变的是str的内容,但是strong却被同时改变了,这是因为strong和str指向的是同一块内存(可以在Xcode中调试View Memory of "*_strong"和View Memory of "*str"可以看到它们的Address是一致的),该内存的引用计数为2,所以改变s的内容实际上就改变了strong的内容

另外如果用一个strong指针来指向不可变对象str,那么str的引用计数不会加1

NSString *str = @"string"; // @"string"存放在内存的常量区(不可变),生命周期为整个程序的生命周期,引用计数为一个很大的数,不会被改变
NSString *__strong s = str; // 试图使str的引用计数加1
NSLog(@"%ld", CFGetRetainCount((__bridge CFTypeRef)(str))); // 引用计数不变


那么如果我们不想让strong和str指向一个地方,这时copy就派上用场了,copy和strong类似,但是它不影响所指向的对象的引用计数,如果str指向的对象是可变的,那么copy会创建一个所指向对象的不可变副本(你不能修改copy指向的地址的内容,即使这个copy是NSMultableString,[str copy]同理),它们不指向同一个内存地址

NSMutableString *str = [[NSMutableString alloc] initWithUTF8String:"mutablestring"]; // 堆中分配内存
member.cp = str; // 头文件定义@property(copy) NSString *cp; cp指向str的副本,cp和str指向不同地址
NSLog(@"%@", member.cp); // 输出mutablestring
[str deleteCharactersInRange:NSMakeRange(0, 7)];
NSLog(@"%@", member.cp); // 然并卵,cp没有改变,输出mutablestring
NSLog(@"%p %p", str, member.cp); // 地址不同

member.mscp = str; // 头文件定义@property(copy) NSMutableString *mscp
NSLog(@"%p %p", str, member.mscp); // 地址不同
[member.mscp deleteCharactersInRange:NSMakeRange(0, 7)]; // mscp指向不可变的副本,即使它是NSMutableString,也不能修改其指向的内容。运行时报错Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with deleteCharactersInRange:'

如果str指向的对象不可变,结果又会不一样

NSString *str = [[NSString alloc] initWithFormat:@"string"]; // str虽然在堆中分配内存,但是@"string"实际上是不能被改变的,这个对象会被添加到自动释放池
member.cp = str;
NSLog(@"%ld", CFGetRetainCount((__bridge CFTypeRef)(str))); // 引用计数为一个很大值
NSLog(@"%p %p", str, member.cp); // cp并没有分配新的空间,因为str指向的内存地址不可改变(也就是说@"string"这个值无法改变,不能变成@"abc"之类的),所以cp和str指向了同一个地址

NSString *str = @"string"; // @"string"存放在内存的常量区(不可变),生命周期为整个程序的生命周期,引用计数为一个很大的数,不会被改变
member.cp = str;
NSLog(@"%ld", CFGetRetainCount((__bridge CFTypeRef)(str))); // 一个非常大的引用计数
NSLog(@"%p %p", str, member.cp); // cp并没有分配新的空间,因为str指向的内存地址不可改变(也就是说@"string"这个值无法改变,不能变成@"abc"之类的),所以cp和str指向了同一个地址

weak和assign不会对所指的对象引用计数加1(还是指向的同一个内存地址),它们的区别就是当weak指向的内存区域被释放时,weak指针会被赋值为nil,而如果用的是assign,不会被赋值为nil,再去使用这个指针时,运行时会报错
NSString *str= [[NSString alloc] initWithFormat:@"%s", "Name:zyu"];
member.weak = str; // 头文件定义@property(weak) NSString *weak; weak和str指向同一个内存地址
str= nil; // str空间释放时,weak被赋值成nil
NSLog(@"%@", member.weak); // 输出(null)
等价于
NSString *str = [[NSString alloc] initWithFormat:@"%s", "Name:zyu"];
NSString * __weak _weak = str; // 还可以用关键字来定义weak属性
str = nil;
NSLog(@"%@", _weak); // 输出(null)
@当我把"Name:zyu"改成"zyu"时,NSLog输出的结果不是(null),不知道是不是Xcode的bug。( ̄▽ ̄)
NSString *str= [[NSString alloc] initWithFormat:@"%s", "Name:zyu"];
member.assign= str; // 头文件定义@property(assign) NSString *assign; assign和str指向同一个内存地址
str= nil; // str空间释放时,assign不会被赋值成nil
NSLog(@"%@", member.assign); // 运行时报错EXC_BAD_ACCESS,有时候又不报错,没有任何输出(╯°□°)╯︵ ┻━┻

Objective-C中的@property: http://www.devtalking.com/articles/you-should-to-know-property/
Transitioning to ARC Release Notes: https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
Objective-c的@property 详解: http://www.cnblogs.com/andyque/archive/2011/08/03/2125728.html
如何正确使用property里面的strong,weak等关健字: http://www.devm.cn/2015/07/16/the-proper-use-of-property-keywords.html
复制对象(一)copy和mutableCopy方法: http://blog.csdn.net/jymn_chen/article/details/18887841


猜你喜欢

转载自blog.csdn.net/ixiaochouyu/article/details/48690453
今日推荐