IOS内存管理浅谈

 1.任何你创建的对象你都能获得其所有权。

    这里的创建包括使用alloc, new ,copy等关键字来获得一个对象。

2 .你可以通过retain来获得一个对象的所有权。
    除了创建对象外,获得某个对象所有权的唯一方法就只有给该对象发retain消息。
一旦通过retain获得了该对象的所有权,就必须遵守上面红字标注的原则:如果你拥有一个对象,那么你就有责任去释放它。

3 .如果你不再需要一个对象了,你就必须释放其所有权。

4 .你不能释放非你所有的对象所有权。

-》所有由alloc、copy(mutablecopy)、retain、new创建的object,必须手动release(或autorelease) 。
autorelease不是自动释放,是AutoreleasePool的实例,在runloop中被”稍后“释放。
  • 创建对象 alloc 、new,初始的retainCount都是1,copy使retainCount加1,
  • mutableCopy的retainCount保持原来的值不变,但是当前的对象的retainCount为1。   
  • 如:NSMutableArray *mArrayCopy1 = [array1 mutableCopy];
  • array1的retainCount保持原来的值不变;mArrayCopy1的retainCount为1;
  •     NSArray *mArray1 = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
         NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);
        
        NSArray *mArrayCopy2 = [mArray1 copy];
        NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);
        
        NSMutableArray *mArrayMCopy1 = [mArray1 mutableCopy];
        NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);
        
        [mArray1 retain];
         NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);

  • 2014-06-17 10:41:45.092 TicketProject[799:907] mArray1 retain count: 1
    2014-06-17 10:41:45.093 TicketProject[799:907] mArray1 retain count: 2
    2014-06-17 10:41:45.093 TicketProject[799:907] mArray1 retain count: 2
    2014-06-17 10:41:48.521 TicketProject[799:907] mArray1 retain count: 3
    
    

    ->copy 与mutableCopy浅谈
  • 1.     系统的非容器类对象
      这里指的是NSString,NSNumber等等一类的对象。
      NSString *string = @"origion";
      NSString *stringCopy = [string copy];
      NSMutableString *stringMCopy = [string mutableCopy];
      [stringMCopy appendString:@"!!"];
      查看内存可以发现,string和stringCopy指向的是同一块内存区域(又叫apple弱引用weak reference),
  • 此时stringCopy的引用计数和string的一样都为2。而stringMCopy则是我们所说的真正意义上的复制,系统为其分配了新内存,但指针所指向的字符串还是和string所指的一样。
      再看下面的例子: 
        NSMutableString *string = [NSMutableString stringWithString: @"origion"];
        NSString *stringCopy = [string copy];
        NSMutableString *mStringCopy = [string copy];
        NSMutableString *stringMCopy = [string mutableCopy];
        [mStringCopy appendString:@"mm"];//error
        [string appendString:@" origion!"];
        [stringMCopy appendString:@"!!"];
    以上四个NSString对象所分配的内存都是不一样的。但是对于mStringCopy其实是个imutable对象,所以上述会报错。
    对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。
  • 如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。
    2.     系统的容器类对象 
    指NSArray,NSDictionary等。对于容器类本身,上面讨论的结论也是适用的,需要探讨的是复制后容器内对象的变化。
        //copy返回不可变对象,mutablecopy返回可变对象

  •     NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];
        NSArray *arrayCopy1 = [array1 copy];

  •     //arrayCopy1是和array同一个NSArray对象(指向相同的对象),包括array里面的元素也是指向相同的指针
        NSLog(@"array1 retain count: %d",[array1 retainCount]);1
        NSLog(@"array1 retain count: %d",[arrayCopy1 retainCount]);2

  •     NSMutableArray *mArrayCopy1 = [array1 mutableCopy];
        //mArrayCopy1是array1的可变副本,指向的对象和array1不同,但是其中的元素和array1中的元素指向的是同一个对象。
  • mArrayCopy1还可以修改自己的对象
        [mArrayCopy1 addObject:@"de"];
  • Printing description of mArrayCopy1:
    <__NSArrayM 0x95e5e40>(
    a,
    b,
    c,
    de
    )


    [mArrayCopy1 removeObjectAtIndex:0];

  • Printing description of mArrayCopy1:
    <__NSArrayM 0x95a97b0>(
    b,
    c,
    de
    )


    array1和arrayCopy1是指针复制,而mArrayCopy1是对象复制,mArrayCopy1还可以改变期内的元素:删除或添加。
  • 但是注意的是,容器内的元素内容都是指针复制。

  • 下面用另一个例子来测试一下。
        NSArray *mArray1 = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
        NSArray *mArrayCopy2 = [mArray1 copy];
  •     NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);2

  •     NSMutableArray *mArrayMCopy1 = [mArray1 mutableCopy];
        NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);2

  •     //mArrayCopy2,mArrayMCopy1和mArray1指向的都是不一样的对象,但是其中的元素都是一样的对象——同一个指针
        //一下做测试
        NSMutableString *testString = [mArray1 objectAtIndex:0];
    [testString appendString:@" tail"];//这样以上三个数组的首元素都被改变了
  • TicketProject[975:907] mArrayMCopy2:(
        "a tail",
        b,
        c
    )
    2014-06-17 11:26:20.624 TicketProject[975:907] mArrayMCopy1:(
        "a tail",
        b,
        c
    )
    2014-06-17 11:26:21.599 TicketProject[975:907] mArrayMCopy2:(
        "a tail",
        b,
        c
    )
    


  • 由此可见,对于容器而言,其元素对象始终是指针复制。如果需要元素对象也是对象复制,就需要实现深拷贝。http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Collections/Articles/Copying.html
        NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"first"],[NSStringstringWithString:@"b"],@"c",nil];
        NSArray *deepCopyArray=[[NSArray alloc] initWithArray: array copyItems: YES];
        NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
        [NSKeyedArchiver archivedDataWithRootObject: array]];
    trueDeepCopyArray是完全意义上的深拷贝,而deepCopyArray则不是,对于deepCopyArray内的不可变元素其还是指针复制。或者我们自己实现深拷贝的方法。因为如果容器的某一元素是不可变的,那你复制完后该对象仍旧是不能改变的,因此只需要指针复制即可。除非你对容器内的元素重新赋值,否则指针复制即已足够。举个例子,[[array objectAtIndex:0]appendstring:@”sd”]后其他的容器内对象并不会受影响。[[array objectAtIndex:1]和[[deepCopyArray objectAtIndex:0]尽管是指向同一块内存,但是我们没有办法对其进行修改——因为它是不可改变的。所以指针复制已经足够。所以这并不是完全意义上的深拷贝,但是apple的官方文档将其列为deep copy了,并添加了copy和mutablity的关系说明,故在此做一说明(这边还有点疑惑,有了解的赐教啊)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值