首页 编程 软件学院 查看内容

iOS内存管理

2013-10-21 11:00 645 0

摘要: 1  配对原则 alloc – release new – release retain - release copy – release ...
关键词: 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]; 
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部