Sian 发表于 2014-1-22 21:43:22

第二十六讲:Objective-C内存管理之深拷贝

继续上一讲的浅拷贝,深拷贝的区别在于是否拷贝对象中的引用对象1、创建一个数组array,将类Car创建三个对象并保存到数组array中,使用[ initWithArray:array]方法将array数组拷贝到array1中,修改array中的car元素,查看array1中的car是否发生变化;
2、使用[ initWithArray:array copyItems:YES]方法将array拷贝到array2中,修改array中的car元素,查看array2中的car是否发生变化;
SACar.h
//
//SACar.h
//DeepCopy
//
//Created by yusian on 14-1-22.
//Copyright (c) 2014年 yusian. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface SACar : NSObject <NSCopying>

@property (assign) NSString * name;
@property int year;

@end
SACar.m
//
//SACar.m
//DeepCopy
//
//Created by yusian on 14-1-22.
//Copyright (c) 2014年 yusian. All rights reserved.
//

#import "SACar.h"

@implementation SACar
//***************************************NSCopying
- (id) copyWithZone:(NSZone *)zone {
    SACar * c = [[[ allocWithZone:zone] init] autorelease];
    c.name = self.name;
    c.year = self.year;
    return c;
}
//***************************************NSCopying_end

- (NSString *) description {
    return ;
}

- (void) dealloc {
    NSLog(@"%@ is dealloc", self.name);
    self.name = nil;
    ;
}

@end
main.m
//
//main.m
//DeepCopy
//
//Created by yusian on 14-1-22.
//Copyright (c) 2014年 yusian. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "SACar.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
      NSMutableArray * array = [ init];
      
      for (int i = 0; i < 3; i ++) {
            SACar * car = [ init];
            car.name = ;
            car.year = 2000 + i;
            ;
            ;
      }
      NSLog(@"%@", array);
      
      NSMutableArray * array1 = [ initWithArray:array];
      [ setName:@"NewCar"];
      NSLog(@"%@", array);
      
      NSMutableArray * array2 = [ initWithArray:array copyItems:YES];
      [ setName:@"SecondCar"];
      NSLog(@"%@", array);
      NSLog(@"%@", array2);
      

//      ;
//      ;
//      ;
    }
    return 0;
}

运行结果:
2014-01-22 21:40:09.327 DeepCopy (
    "Car0 age is 2000",
    "Car1 age is 2001",
    "Car2 age is 2002"
)
2014-01-22 21:40:09.329 DeepCopy (
    "NewCar age is 2000",
    "Car1 age is 2001",
    "Car2 age is 2002"
)
2014-01-22 21:40:09.329 DeepCopy (
    "NewCar age is 2000",
    "Car1 age is 2001",
    "Car2 age is 2002"
)
2014-01-22 21:40:09.329 DeepCopy (
    "SecondCar age is 2000",
    "Car1 age is 2001",
    "Car2 age is 2002"
)
2014-01-22 21:40:09.330 DeepCopy Car2 is dealloc
2014-01-22 21:40:09.330 DeepCopy Car1 is dealloc
2014-01-22 21:40:09.330 DeepCopy SecondCar is dealloc
Program ended with exit code: 0结果表示:
进行浅拷贝后,修改array中的Car0为“NewCar”后,array与array1中的Car0都变成了NewCar;
进行深拷贝后,修改array2中的Car0为“SecondCar”后,array中的Car0依然为之前的NewCar;
array2打印出来的结果中,Car0被修改成SecondCar,并且array2被自动释放,array与array1却没有,为什么?

Sian 发表于 2014-1-22 22:55:30

深拷贝还可以通过归档的方式来实现:
1、创建好的数组array归档到data中;
2、将data解档到array1中,该过程会将归档的数据读出重新加载到数组array1中;
3、需要注意的是:前面使用数组的copy方法,Car中的Name属性为assign,使用数组copy后会自动内存管理,但通过归档方式实现,解档时会报错,因此,在声明属性时,需要使用copy属性:@property(copy) NSString * name;
代码如下:
SACar.h
//
//SACar.h
//DeepCopy
//
//Created by yusian on 14-1-22.
//Copyright (c) 2014年 yusian. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface SACar : NSObject <NSCopying, NSCoding>

@property (copy) NSString * name;
@property int year;

@end

SACar.m
//
//SACar.m
//DeepCopy
//
//Created by yusian on 14-1-22.
//Copyright (c) 2014年 yusian. All rights reserved.
//

#import "SACar.h"

@implementation SACar
//***************************************NSCopying
- (id) copyWithZone:(NSZone *)zone {
    SACar * c = [[[ allocWithZone:zone] init] autorelease];
    c.name = self.name;
    c.year = self.year;
    return c;
}
//***************************************NSCopying_end

//***************************************NSCoding
- (void) encodeWithCoder:(NSCoder *)aCoder {
    ;
    ;
}


- (id) initWithCoder:(NSCoder *)aDecoder {
    if (self = ) {
      self.name = ;
      self.year = ;
    }
    return self;
}
//***************************************NSCoding_end

- (NSString *) description {
    return ;
}

- (void) dealloc {
    NSLog(@"%@ is dealloc", self.name);
    self.name = nil;
    ;
}

@end

main.m
//
//main.m
//DeepCopy
//
//Created by yusian on 14-1-22.
//Copyright (c) 2014年 yusian. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "SACar.h"

int main(int argc, const char * argv[])
{
   
    @autoreleasepool {
      NSMutableArray * array = [ init];
      
      for (int i = 0; i < 3; i ++) {
            SACar * car = [ init];
            car.name = ;
            car.year = 2000 + i;
            ;
            ;
      }
      NSLog(@"%@", array);
      
      NSData * data = ;
      NSMutableArray * array1 = ;
      [ setName:@"NewCar"];
      NSLog(@"%@", array);
      
      ;
      //;
   
    }
    return 0;
}

输出结果:
2014-01-22 22:46:06.956 DeepCopy (
    "Car0 age is 2000",
    "Car1 age is 2001",
    "Car2 age is 2002"
)
2014-01-22 22:46:06.958 DeepCopy (
    "Car0 age is 2000",
    "Car1 age is 2001",
    "Car2 age is 2002"
)
2014-01-22 22:46:06.958 DeepCopy Car0 is dealloc
2014-01-22 22:46:06.959 DeepCopy Car1 is dealloc
2014-01-22 22:46:06.959 DeepCopy Car2 is dealloc
2014-01-22 22:46:06.959 DeepCopy NewCar is dealloc
2014-01-22 22:46:06.960 DeepCopy Car1 is dealloc
2014-01-22 22:46:06.960 DeepCopy Car2 is dealloc
Program ended with exit code: 0
同样的道理,通过归档进行深拷贝的对象不需要release,这与@autoreleasepool有关系,原因暂未知;
页: [1]
查看完整版本: 第二十六讲:Objective-C内存管理之深拷贝