IOS学习笔记之对象复制

1、复制对象的基本概念

     复制对象就是复制一个对象作为副本,它会开辟一块新的内存(堆内存)来存储副本对象,就像复制文件一样。即源对象和副本对象是两块不同的内存区域。


2、OC中提供的对象拷贝方法有copy和mutableCopy.
     copy方法用于复制对象的不可变副本。即,用copy拷贝的对象是不可修改的。一个可变对象用copy方法拷贝得到的对象也是不可修改的。
  例如:用一个不可变数组拷贝一个对象,和用一个可变数组拷贝一个睇相
           
          

NSMutableArray *muArray = [NSMutableArrayarrayWithObjects:@"zhangsan",@"lisi",nil];

//copy复制了一份不可修改的副本

NSArray *array2 = [muArray copy];

此时array2是不可修改的,它是不可变的。

    mutableCopy方法用于复制对象的可变副本。即,用mutableCopy复制得到的对象是可变的。一个不可变对象使用mutableCopy方法赋值得到的对象也是可变的。

   例如:一个不可变数组使用mutable方法进行复制,会得到一个可变的数组

         NSArray *array1 =@[@"one",@"two",@"three"];

        //mutableCopy复制了array1的一份可修改的副本

        NSMutableArray *array = [array1 mutableCopy];

        NSLog(@"%@",array);

        [array addObject:@"four"];

        NSLog(@"%@",array);

     结果为:

      


3、retain和copy的区别
     retain是指针拷贝,copy是对象拷贝

 NSMutableArray *muArray = [NSMutableArrayarrayWithObjects:@"zhangsan",@"lisi",nil]; 

 NSMutableArray *muArray1 = [muArray retain];

        //因为retain是指针拷贝,所以muArraymuArray1的指针相同

        //muArray1 移除一个元素,muArray也会移除一个元素

        [muArray1 removeObject:@"lisi"];

        NSLog(@"%@",muArray);

        NSLog(@"%@",muArray1);

     

4、实现自定义对象的复制功能

   首先定义一个类:

@interface Person : NSObject

@property (nonatomic,retain)NSMutableString *userName;

@property (nonatomic,assign)int age;

@end

   若直接对自定义对象进行拷贝

        Person *person = [[Personalloc] init];

        person.userName = [NSMutableStringstringWithString:@"张三"];

        person.age = 19;

        Person *copyPerson = [person copy];



  上述结果表明,直接对自定义对象进行拷贝,程序将会崩溃。

  那么,要如何对自定义对象进行拷贝呢?

  当程序调用对象的copy方法来复制对象时,程序底层需要调用copyWithZone方法来完成实际的复制工作,copy返回的实际上就是copyWithZone方法的返回值。

  当程序调用mutableCopy方法来复制对象时,程序底层需要调用mutableCopyWithZone方法来完成实际的复制工作,mutableCopy实际上就是返回mutableCopyWithZone方法的返回值。

  为了实现自定义对象的拷贝,通常需要类实现NSCopying协议和copyWithZone方法,或者NSMutableCopy协议和mutableCopyWithZone方法。

  @interface Person :NSObject<NSCopying>

  @property (nonatomic,retain)NSMutableString *userName;

  @property (nonatomic,assign)int age;

  @end

@implementation Person

-(id)copyWithZone:(NSZone *)zone{

    Person *person = [[[selfclass] allocWithZone:zone]init];

    person.userName =_userName;

    person.age = _age;

    return person;

}

@end
    这样即可实现自定义对象的拷贝

        Person *person = [[Personalloc] init];

        person.userName = [NSMutableStringstringWithString:@"张三"];

        person.age = 19;

        Person *copyPerson = [person copy];

        NSLog(@"copyPersonuserName:%@",copyPerson.userName);

        NSLog(@"personuserName:%@",person.userName);

     

5、浅拷贝和深拷贝

   浅拷贝(shallow copy),当对象的属性是指针变量时,如果程序只是复制该指针的地址,而不是真正复制指针所指向的对象,这种方式就称为浅拷贝

    深拷贝(deep copy),深拷贝不仅会复制对象的本身,而且会递归复制每个指针类型的属性,直到两个对象没有任何的公用部分为止。

    继续以上述例子中的Person类为例:

    若改变person属性userName的值,会发生什么呢?

        Person *person = [[Personalloc] init];

        person.userName = [NSMutableStringstringWithString:@"张三"];

        person.age = 19;

        Person *copyPerson = [person copy];

        //给person对象中的username属性拼接一个字符串@"11111"

        [person.userName appendString:@"11111"]; 

        NSLog(@"copyPersonuserName:%@",copyPerson.userName);

        NSLog(@"personuserName:%@",person.userName);



     为什么出现上述情况呢?

      person.userName和copyPerson.userName都指向了同一块内存
      只是改变了person.userName,结果copyPerson.userName的值也改变了。这种情况说明自定义对象只实现了浅拷贝,若要实现深拷贝则要对每个对象属性进行拷贝。
      

-(id)copyWithZone:(NSZone *)zone{

    Person *person = [[[selfclass] allocWithZone:zone]init];

    person.userName = [_userNamecopy];//对对象属性进行拷贝

    person.age = _age;

    return person;

}


执行结果变为:


这样person和copyPerson就完全没有共同部分,因此实现了深拷贝。


     
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值