首页 > 学院 > 开发设计 > 正文

OC语言-08-深拷贝与浅拷贝详解(示例)

2019-11-14 18:20:49
字体:
来源:转载
供稿:网友

概述


  • 拷贝:复制一个与源对象内容相同的对象
  • 实现拷贝,需要遵守以下两个协议

    • NSCopying
    • NSMutableCopying
  • 拷贝返回对象的种类

    • 可变,mutableCopy消息返回的对象
    • 不可变,copy消息返回的对象
  • 拷贝的种类

    • 浅拷贝,只是复制了一个指向源对象的指针,未创建对象,未分配内存
    • 深拷贝,复制了源对象,创建了新对象,分配了内存
  • 注意

    • 系统对容器类的对象与非容器类的对象的内存处理是不同的,即当一个没有被其他对象强引用的对象从容器中移除后,该对象就销毁

Copy与Retain


  • copy

    • 是创建一个新的对象,内容拷贝
    • copy表示的是两个对象的内容相同, 新对象的引用计数为1
    • 与旧对象的引用计数无关,就对象没有变化
    • copy减少了对象对上下文的
  • retain

    • 创建的是一个指针,指针拷贝
    • 对象地址相同,内容固然相同
    • 对象的引用计数+1

不同对象的拷贝行为


  • 非容器对象(如NSString))

    • 对于不可变对象

      • 规则

        • copy,浅拷贝(指针复制)
        • mutableCopy,深拷贝(对象复制),返回对象可变(产生新的 可变对象)
      • 示例

        - (void)imutableInstanceCopy{    NSString *string = @"Welcome to Xcode";    //copy,浅拷贝    NSString *stringCopy = [string copy];    //mutableCopy,返回的对象可变    NSMutableString *stringMutableCopy = [string mutableCopy];    [stringMutableCopy appendString:@"!"];    //string与stringCopy的内存地址相同    NSLog(@"string: %p", string);    NSLog(@"strongCopy: %p", stringCopy);    //string与stringMutableCopy的内存地址不同,分配了新的内存    NSLog(@"stringMCopy:%p", stringMutableCopy);}
    • 对于可变对象

      • 规则

        • copy,深拷贝(对象复制),返回对象不可变
        • mutableCopy,深拷贝(对象复制)
      • 示例

        - (void)mutableInstanceCopy{    NSMutableString *mutableString = [NSMutableString stringWithString: @"Welcome to Xcode"];    //深拷贝,返回对象不可变    NSString *stringCopy = [mutableString copy];    NSMutableString *mutableStringCopy = [mutableString copy];    //运行时,此句会报错,错误信息“Attempt to mutate immutable object with appendString:”    [mutableStringCopy appendString:@"~~~"];    //深拷贝,返回对象可变    NSMutableString *stringMutableCopy = [mutableString mutableCopy];    [stringMutableCopy appendString:@"!"];    //三者与mutableString的内存地址都不同    NSLog(@"mutableString: %p", mutableString);    NSLog(@"string: %p", stringCopy);    NSLog(@"mutableStringCopy: %p", mutableStringCopy);    NSLog(@"stringMutbleCopy:%p", stringMutableCopy);}
  • 容器对象(NSArray

    • 遵循非容器对象的拷贝原则
    • 注意

      • 容器内的元素是指针赋值(浅拷贝)
      • 示例

        - (void)containerInstanceShallowCopy{    NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"Welcome"],@"to",@"Xcode",nil];    //浅拷贝    NSArray *arrayCopy = [array copy];    //深拷贝    NSMutableArray *arrayMutableCopy = [array mutableCopy];    NSLog(@"array: %p", array);    NSLog(@"arrayCopy: %p", arrayCopy);    NSLog(@"arrayMutableCopy: %p", arrayMutableCopy);    //容器内的对象是浅拷贝,即它们在内存中只有一份    NSMutableString *testString = [array objectAtIndex:0];    [testString appendString:@" you"];    //三个数组的内容同时改变    NSLog(@"array[0]: %@", array[0]);    NSLog(@"arrayCopy[0]: %@", arrayCopy[0]);    NSLog(@"arrayMutableCopy[0]: %@", arrayMutableCopy[0]);}
    • 实现真正意义上的深复制

      - (void)containerInstanceDeepCopy{    NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"Welcome"],@"to",@"Xcode",nil];    //数组内对象是指针复制    NSArray *deepCopyArray = [[NSArray alloc] initWithArray:array];    //真正以上的深复制,数组内对象是对象复制    NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];    NSLog(@"array: %p", array);    NSLog(@"deepCopyArray: %p", deepCopyArray);    NSLog(@"trueDeepCopyArray: %p", trueDeepCopyArray);    //改变array的第一个元素    [[array objectAtIndex:0] appendString:@" you"];    //只影响deepCopyArray数组的第一个元素    NSLog(@"array[0]: %@", array[0]);    NSLog(@"arrayCopy[0]: %@", deepCopyArray[0]);    //不影响trueDeepCopyArray数组的第一个元素,是真正意义上的深拷贝    NSLog(@"arrayMutableCopy[0]: %@", trueDeepCopyArray[0]);}
  • 自定义对象

    • 在定义对象要实现拷贝,需要遵守NSCoping与NSMutableCoping协议,并实现以下方法

      • - (id)copyWithZone:(NSZone *)zone,可变拷贝
      • - (id)mutableCopyWithZone:(NSZone *)zone,不可变拷贝
    • 示例(自定对象Person的拷贝)

      • 遵守协议,设置成员属性

        @interface Person : NSObject <NSCopying, NSMutableCopying>/**姓名*/@PRoperty (nonatomic, copy) NSMutableString *name;/**地址*/@property (nonatomic, copy) NSString *address;/**年龄*/@property (nonatomic, assign) NSInteger age;@end
      • 重写初始化方法

        - (instancetype)init{    if (self = [super init])    {        self.name = [[NSMutableString alloc] initWithString:@"XiaoYaowang"];        self.address = @"世俗孤岛";        self.age = 3;    }    return self;}
      • 实现- (id)copyWithZone:(NSZone *)zone

        - (id)copyWithZone:(NSZone *)zone{    Person *p = [[[self class] allocWithZone:zone] init];    p.name = [self.name copy];    p.address = [self.address copy];    p.age =  self.age;    return p;}
      • 实现- (id)mutableCopyWithZone:(NSZone *)zone

        - (id)mutableCopyWithZone:(NSZone *)zone{    Person *p = [[[self class] allocWithZone:zone] init];    //注意,此处是mutableCopy方法    p.name = [self.name mutableCopy];    p.address = [self.address copy];    p.age =  self.age;    return p;}

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表