copy和mutable copy

作者: coderhlt | 来源:发表于2017-07-18 10:09 被阅读30次

最近上班没事,就学会习,继续记录下最近学到的东西,与君共勉,大神勿喷。
首先我们测试一下这两行代码:

  • 测试一:源对象为可变字符串
- (void)test1{
     NSMutableString *string=[NSMutableString stringWithFormat:@"1234"];//源对象:不可变字符串
     NSString *str1=[string copy];//深拷贝
    //只要调用了copy返回对象就是不可变字符串,而源对象是可变字符串,为了不影响源对象字符串,将会内容拷贝一份生成新的对象字符串。
    NSLog(@"%p %p",string,str1);//地址不一样,说明产生了新对象
    NSLog(@"%@ %@",string,str1);//内容一样,说明拷贝了内容
    
    NSMutableString *str2=[string mutableCopy];//深拷贝
    //只要调用了mutableCopy返回对象就是可变字符串,而源对象是也是可变字符串,为了不影响源对象字符串,将会内容拷贝一份生成新的对象字符串。
    NSLog(@"%p %p",string,str2);//地址不一样,说明产生了新对象
    NSLog(@"%@ %@",string,str2);//内容一样,说明拷贝了内容
}
  • 测试二:源对象为不可变字符串
- (void)test2{
 NSString *string=@"1234";//源对象:不可变字符串
    NSString *str1=[string copy];//浅拷贝
    //只要调用了copy返回对象就是不可变字符串,而源对象是不可变字符串,返回对象也是不可变的字符串,因此系统索性会直接拷贝一份内存地址,不会产生新的对象字符串。
    NSLog(@"%p %p",string,str1);//打印地址一样,说明了没有新对象产生
    NSLog(@"%@ %@",string,str1);//打印一样说明了,说明拷贝了地址
    
    
    NSMutableString *str2=[string mutableCopy];//深拷贝
    //只要调用了mutableCopy返回对象就是可变字符串,而源对象是是不可变字符串,为了不影响源对象字符串,将会内容拷贝一份生成新的对象字符串。
    NSLog(@"%p %p",string,str2);//地址不一样,说明产生了新对象
    NSLog(@"%@ %@",string,str2);//内容一样,说明拷贝了内容

}

总结:字符串的拷贝,只要拷贝后是可变的还是不可变的只取决于是调用了copy还是mutablecopy,只要调用了copy返回对象就是不可变字符串,只要调用了mutableCopy返回对象就是可变字符串.源对象为不可变字符串时,并调用了copy方法时属于浅拷贝。浅拷贝就是指针的拷贝不会产生新对象,深拷贝是内容的拷贝会产生新对象。结合上面的例子和经验,继续测试一下

  • 测试三:源对象为数组
- (void)test3{
   NSMutableArray *Marray=[NSMutableArray arrayWithObjects:@"1", nil];
    NSArray *array=[Marray copy];//只要调用了copy返回对象就是不可变的
    NSLog(@"%p %p",Marray,array);
    NSLog(@"%@ %@",Marray,array);
   //地址不一样,内容一样:深拷贝;
    
    NSMutableArray *mutablearray=[Marray mutableCopy];//只要调用了mutablecopy返回对象就是可变的
    NSLog(@"%p %p",Marray,mutablearray);
    NSLog(@"%@ %@",Marray,mutablearray);
    //地址不一样,内容一样:深拷贝;
    
    
    NSArray *array1=@[@"2",@"2"];
    NSArray *array11=[array1 copy];//浅拷贝
    NSLog(@"%p %p",array1,array11);
    NSLog(@"%@ %@",array1,array11);
   //地址一样,内容一样:浅拷贝;
    
    NSMutableArray *array2=[array1 mutableCopy];
    NSLog(@"%p %p",array1,array2);
    NSLog(@"%@ %@",array1,array2);
   //地址不一样,内容一样:深拷贝;

}

总结:字符串,数组,字典.....的拷贝过程一样,只要调用了mutablecopy返回对象就是可变的,只要调用了copy返回对象就是不可变的。只要源对象是不可变的,调用了copy,只是指针的拷贝,不会有新对象的产生是浅拷贝, 而调用了mutablecopy,就会产生新对象,是深拷贝。其他的源对象是可变的,都属于深拷贝。

自定义类的拷贝

- (void)viewDidLoad {
    [super viewDidLoad];
    Person *p=[[Person alloc]init];
    p.name=@"张三";
    p.age=@"24";
    Person *p1=[p copy];
    NSLog(@"%@ %@",p1.age,p1.name);
}

#import "Person.h"
@interface Person()<NSCopying>

@end
@implementation Person
- (id)copyWithZone:(NSZone *)zone{
    Person *p=[[Person allocWithZone:zone]init];
    p.age=self.age;
    p.name=self.name;
    
    
    return p;
}

@end

属性copy,strong

  • copy修饰属性
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,copy)NSArray *array;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
 NSMutableArray *MArray=[NSMutableArray array];
    self.array=MArray;
    NSLog(@"%p %p",MArray,self.array);//打印得到内存地址不同
    [MArray addObject:@"1"];
    //Marray数组添加元素@“1”后,Marray不发生变化
    NSLog(@"%@ %@",MArray,self.array);//打印得到内容不同,说明Marray与self.array互不影响
    
}
- (void)setArray:(NSArray *)array{
    NSArray *arr=[array copy];//深拷贝,arr与array是不同的对象
   _array=arr;//_array与array是不同的对象
}

代码说明:以copy修饰的属性,调用的set方法如上:在给成员变量赋值之前,内部先要调用copy方法返回不可变对象,由于源对象Marray是可变的,所有会深拷贝,重新生一个数组对象。即:self.array=Marray是两个不同内存的对象,以后两者改变互不影响。

  • copy修饰可变对象所引起的崩溃错误
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,copy)NSMutableArray *array;
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.array=[NSMutableArray arrayWithObjects:@"1", nil];
    [self.array addObject:@"1"];
}

运行以上代码后会崩溃: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSingleObjectArrayI addObject:]: unrecognized selector sent to instance 0x6100000043c0'这就是因为错误的修饰所造成的错误。上面代码属性array用copy修饰后返回的真实对象类型是不可变的,即self.array是不可变数组,而不可变数组是不能进行数组的修改,因此系统会以找不到方法2⃣️发生崩溃

  • strong修饰属性
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,strong)NSArray *array;
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSMutableArray *MArray=[NSMutableArray array];
    self.array=MArray;
    NSLog(@"%p %p",MArray,self.array);//打印得到内存地址相同
    [MArray addObject:@"1"];
    //Marray数组添加元素@“1”后,self.array也会添加元素@“1”,因为self.array与Marray所指向的同一地址的对象。
    NSLog(@"%@ %@",MArray,self.array);//内容相同,Marray与self.array互相影响。
}
- (void)setArray:(NSArray *)array{
   _array=array;//_array与array指针拷贝
}

代码说明:以strong修饰的属性,set方法赋值就是单纯的指针拷贝,不会有新对象产生。即self.array=Marray是两个相同内存的同一个对象,两者改变互相影响。
总结:以stong或copy修饰的属性的区别是:copy在赋值前会先调用copy返回一个不可变对象再赋值给成员变量,set方法传入的源对象如果是可变的,返回的不可变对象就是深拷贝出的一个新对象,这样成员变量和源对象就是两个不同对象,因此两者也不会相互影响。而以strong修饰的属性就是单纯的浅拷贝,最终也是同一对象,两者会互相影响。数组,字典,字符串道理同上。。。。。。。。。。

相关文章

  • copy和mutable copy

    最近上班没事,就学会习,继续记录下最近学到的东西,与君共勉,大神勿喷。首先我们测试一下这两行代码: 测试一:源对象...

  • copy & mutable copy

  • copy和mutable-copy

    首先我们测试一下这两行代码: 测试一:源对象为可变字符串 测试二:源对象为不可变字符串 总结:字符串的拷贝,只要拷...

  • (六) [OC高效系列]弄清楚属性

    1.copy mutable copy NSString与NSMutableString 打印如下 NSValue...

  • copy&mutable Copy

    在OC中拷贝分为深拷贝和浅拷贝两种情况。目前存在两种说法,今天主要阐述的是本人认为比较易懂得说法。 不可变对象执行...

  • copy和mutableCopy

    copy和mutableCopy的概念 copy浅拷贝,不拷贝对象本身,仅仅是拷贝指向对象的指针。 mutable...

  • 静态分析错误解析

    1.Property of mutable type 'NSMutableArray' has 'copy' at...

  • iOS 静态分析Analyze

    1.Property of mutable type 'NSMutableArray' has 'copy' at...

  • Objective-C NS对象 copy 方法总结

    1.copy 返回的是不可变对象(immutableObject),即便原消息接收者是mutable对象,copy...

  • iOS copy关键字

    对NSMutableDictionary设置copy属性会导致mutable失效 [__NSDictionaryI...

网友评论

  • lcc小莫:大牛你真棒,排队给你生猴子:heart_eyes::heart_eyes:
    coderhlt:这句话你和多少人都说了吧,不要脸

本文标题:copy和mutable copy

本文链接:https://www.haomeiwen.com/subject/bjyckxtx.html