| 关键词: nbsp retainCount NSLog retain 2013 Test after address NSString str1 |
1 配对原则 alloc – release new – release retain - release copy – release 2 new和alloc-init的区别 (1)先看看实现源码 +new { id newObject =(*_alloc)((Class)self, 0); Class metaClass = self->isa; if (class_getVersion(metaClass)> 1) { return [newObject init]; } else { return newObject; } } +alloc { return(*_zoneAlloc)((Class)self, 0, malloc_default_zone()); } -init { return self; } 通过源码我们发现,[className new]基本等同于[[classNamealloc] init]; 区别只在于alloc分配内存的时候使用了zone. 这个zone是个什么呢? 它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提升了程序处理速度。 (2)为什么不推荐使用new 因为若用了new,则初始化方法只能是init。这样,假如你想调用initWithFrame,initWithVideoId, initWithPlayItem是无法做到的。另一个原因是习惯和风格的问题。 3 NSString 对象为何用copy (1)NSString在Objective-C中是一种非常特殊的对象,其引用系数不受引用计数规则的控制。NSString对象不管是alloc、retain还是release,其引用计数都是-1。看下面一段代码: NSString *aStr = [[NSString alloc] initWithString:@"abc"]; NSLog(@"aStr address = %p", aStr); NSLog(@"aStr retainCount after alloc = %d", [aStr retainCount]); NSString *bStr = [aStr copy]; NSLog(@"aStr retainCount after copy = %d", [aStr retainCount]); NSLog(@"bStr address = %p", bStr); NSLog(@"bStr retainCount = %d", [bStr retainCount]); NSString *cStr = [aStr retain]; NSLog(@"aStr retainCount after retain = %d", [aStr retainCount]); NSLog(@"cStr address = %p", cStr); NSLog(@"cStr retainCount = %d", [cStr retainCount]); [aStr release]; NSLog(@"aStrretainCount after release = %d", [aStr retainCount]); 输出结果: 2013-10-15 21:51:11.916Test[5575:a0b] aStr address = 0x3548 2013-10-15 21:51:11.918Test[5575:a0b] aStr retainCount after alloc = -1 2013-10-15 21:51:11.919Test[5575:a0b] aStr retainCount after copy = -1 2013-10-15 21:51:11.919Test[5575:a0b] bStr address = 0x3548 2013-10-15 21:51:11.919Test[5575:a0b] bStr retainCount = -1 2013-10-15 21:51:11.920Test[5575:a0b] aStr retainCount after retain = -1 2013-10-15 21:51:11.920Test[5575:a0b] cStr address = 0x3548 2013-10-15 21:51:11.921Test[5575:a0b] cStr retainCount = -1 2013-10-15 21:51:11.921 Test[5575:a0b] aStrretainCount after release = -1 (2)对于NSMutableString,看下面一段代码 NSMutableString *str1 = [[NSMutableString alloc] initWithString:@"abc"]; NSLog(@"str1 address = %p", str1); NSLog(@"str1 retaincount after alloc = %d", [str1 retainCount]); NSString *str2 = [str1 copy]; NSLog(@"str1retaincount after copy = %d", [str1 retainCount]); NSLog(@"str2 address = %p", str2); NSLog(@"str2 retaincount = %d", [str2 retainCount]); NSString *str3 = [str1 retain]; NSLog(@"str1 retaincount after retain = %d", [str1 retainCount]); NSLog(@"str3 address = %p", str3); NSLog(@"str3 retaincount = %d", [str3 retainCount]); [str1 setString:@"edf"]; NSLog(@"str1 address = %p", str1); NSLog(@"after str1 changed, str2 = %@", str2); NSLog(@"afterstr1 changed, str3 = %@", str3); 运行结果: 2013-10-15 22:14:51.735Test[5794:a0b] str1 address = 0x8c46510 2013-10-15 22:14:51.736Test[5794:a0b] str1 retaincount after alloc = 1 2013-10-15 22:14:51.737Test[5794:a0b] str1 retaincount after copy = 1 2013-10-15 22:14:51.737Test[5794:a0b] str2 address = 0x8c47680 2013-10-15 22:14:51.738Test[5794:a0b] str2 retaincount = 1 2013-10-15 22:14:51.738Test[5794:a0b] str1 retaincount after retain = 2 2013-10-15 22:14:51.739Test[5794:a0b] str3 address = 0x8c46510 2013-10-15 22:14:51.739Test[5794:a0b] str3 retaincount = 2 2013-10-15 22:14:51.739Test[5794:a0b] str1 address = 0x8c46510 2013-10-15 22:14:51.740Test[5794:a0b] after str1 changed, str2 = abc 2013-10-15 22:14:51.740 Test[5794:a0b] after str1changed, str3 = edf 从(1)中的结果可以看出,对于NSString来说,用alloc和用retain都是指向同一块内存,区别不大。 但从(2)中来看,对于NSMutableString来说,alloc实际上就是开辟了一块新内存,再把内容复制进来,而retain内存不变引用计数+1。如果NSMutableString中的内容被改变了的话,用retain之后的str3内容也被改变。这是写程序过程中所不想要的结果。所以这种情况下,用copy比较安全。 另外,因为苹果的官方SDK,都把NSString属性声明为copy,比如UILabel中的两个属性: @property(nonatomic,copy) NSString *text; //default is nil @property(nonatomic,copy) NSAttributedString *attributedText NS_AVAILABLE_IOS(6_0); // default is nil 所以规范上在声明NSString或其相关子类属性变量时,都声明为copy。 4 强引用与弱引用(retain, assign,strong, weak) retain为强引用,会导致引用计数+1。想象一下一只小狗被一根绳子拴着,强引用一次就相当于多了一条绳子。只有在所有绳子断开之后,小狗才会跑开。 assign为弱引用,不会引起引用计数的变化。想象一下一只小狗被一根绳子拴着,一个或一群小孩子指着小狗说:快看,这里有条小狗!不管有多少个小孩子用手指指着那条狗,只要那条绳子断开,小狗就会跑掉。 weak和strong只有你打开ARC时才会被要求使用。这时你无法使用retain/release/autorelease。strong等价于retain。weak大体上相当于assign,区别在于weak比assign多了一个功能,当对象消失后自动把指针变成nil,好处不言而喻。 assign除了了可以用来修饰基本类型,如布尔型,整型,浮点型外,一些对象也要使用assign。举两个最常见的例子。 例一:delegate假如用retain会有什么后果? 在AController.m中的某个方法内有如下代码: _bView = [[BView alloc]initWithFrame:frame];
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|