iOS 的strong和copy

之前有过一篇文章关于iOS 属性的 iOS指示符 assign、copy、retain、strong、weak,之后看了一遍有总结了一下:

NSString 选 Strong 还是copy?

1、现分别创建NSString 的strong 和 copy 两个属性


@property(nonatomic, strong) NSString *age1;
@property(nonatomic, copy) NSString *age2; 

2、创建一个NSString 常量,赋值给上面的age1和age2两个属性。

    NSString *age = @"11";
    NSLog(@"age:  %@ - %p", age, age);
    self.age1 = age;
    self.age2 = age;
    NSLog(@"age1: %@ - %p", self.age1, self.age1);
    NSLog(@"age2: %@ - %p", self.age2, self.age2);
    
    NSString *ageOther = [age stringByAppendingString:@"20"];
    NSLog(@"age:  %@ - %p", age, age);
    NSLog(@"ageother:  %@ - %p", ageOther, ageOther);
    NSLog(@"age1: %@ - %p", self.age1, self.age1);
    NSLog(@"age2: %@ - %p", self.age2, self.age2);

3、结果:

 age:  11 - 0x108f28078              
 age1: 11 - 0x108f28078              
 age2: 11 - 0x108f28078              
 age:  11 - 0x108f28078              
 ageother:  1120 - 0x600000255000    
 age1: 11 - 0x108f28078              
 age2: 11 - 0x108f28078              

分析:
我们可以发现,给age1和age2 赋值一个不可变的字符串的时候,都进行了浅拷贝,只拷贝了指针地址,使age、age1、age2都指向同一个地址,在对age进行增加字符串时,因为age是不可变字符串,所以age没有变化,于是age1、age2都没有变化。

总结:声明String和copy属性的String被不可变String赋值时,没有变化,都是浅拷贝,都不会发生变化。

1、现分别创建NSString 的strong 和 copy 两个属性


@property(nonatomic, strong) NSString *str1;
@property(nonatomic, copy) NSString *str2;

2、创建一个NSMutableString 可变字符串,赋值给上面的str1和str2两个属性。

    NSMutableString *name = [[NSMutableString alloc] initWithString:@"Alex"];
    NSLog(@"name : %@ - %p", name, name);
    self.str1 = name;
    self.str2 = name;
    NSLog(@"str1 %@ - %p", self.str1, self.str1);
    NSLog(@"str2 %@ - %p", self.str2, self.str2);
    
    [name appendString:@"Le"];
    
    NSLog(@"str1 %@ - %p", self.str1, self.str1);
    NSLog(@"str2 %@ - %p", self.str2, self.str2);

3、结果:

 name : Alex - 0x604000255cc0       
 str1 : Alex - 0x604000255cc0       
 str2 : Alex - 0xa00000078656c414   

 str1 : AlexLe - 0x604000255cc0     
 str2 : Alex - 0xa00000078656c414              

分析:
我们可以看出在用可变字符串给属性变量赋值时,strong的str1 对name进行浅拷贝,只拷贝了地址,所以str1和name指向同一个地址,而copy 的 str2 对name 进行了深拷贝,str2将name复制到一个新空间内。
当我们对name增添时,此时我们可以看到和name指向相同的str1的内容改变了,而新开辟空间的str2却还保持原来的值。

总结:

声明String和copy属性的String被可变的NSMutableString name赋值时,strong类型的会随可变字符串的变化而变化,但是copy类型的却不会随可变字符串的变化而变化。所以当属性被不可变的字符串赋值时,strong和copy没有区别;当属性被可变字符串赋值时,copy不会被修改,而strong会被修改。综上所述,copy更简单、安全。

NSArray 和 NSMutableArray 是 copy 还是 strong?

1、NSMutableArray 不能被copy修饰,因为以后对数组的增删改操作在copy之后数组都会变成不可变数组,对其进行增删改都将crash。

      @property (copy) NSMutableArray * a;
      NSMutableArray* b = [NSMutableArray array];
      a = b;

等同于

       @property (strong) NSMutableArray * a;
       NSMutableArray* b = [NSMutableArray array];
       a = [b copy];

a在被copy之后就变成了不可变数组NSArray了。

2、NSMutableArray 被strong修饰,在赋值的时候就如上面说的那样会指向同一个地址,被定义的属性也不会改变。

@property(nonatomic, strong) NSMutableArray *arrayA;
@property(nonatomic, copy) NSMutableArray *arrayB;
    NSMutableArray *arrayC = [NSMutableArray array];
    NSLog(@"arrayC.class: %@ - %p", arrayC.class, arrayC);
    self.arrayA = arrayC;
    self.arrayB = arrayC;
    NSLog(@"arrayA.class: %@ - %p", _arrayA.class, _arrayA);
    NSLog(@"arrayB.class: %@ - %p", _arrayB.class, _arrayB);
    
    [self.arrayA removeAllObjects];
    [self.arrayB removeAllObjects];

结果:

arrayC.class: __NSArrayM - 0x604000251220                                                                                                                                   
arrayA.class: __NSArrayM - 0x604000251220                                                                                                                                   
arrayB.class: __NSArray0 - 0x6000000021a0                                                                                                                                   
-[__NSArray0 removeAllObjects]: unrecognized selector sent to instance 0x6000000021a0                                                                                       
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArray0 removeAllObjects]: unrecognized selector sent to instance 0x6000000021a0' 

分析:我们可以看到arrayA 和 arrayC的指向同一个地址,且类型都是mutable的,arrayB的类型发生了改变变成不可变的类型。所以,NSMutableArray被copy修饰之后就变成不可变的,在对其操作时容易crash。
而NSArray被copy或者strong修饰的时候和NSString相同。

1、当arrayA被strong修饰,且被可变数组赋值,可变数组arrayMB改变,被strong修饰属性arrayA也做同样修改,arrayA和arrayMB指向的地址相同;
2、当array被copy修饰,且被可变数组赋值,可变数组arrayMB改变,被copy修饰的属性arrayB没有被修改,因为arrayB深拷贝arrayMB,arrayB和arrayMB在两个内存块中。
3、不管array被strong、copy修饰,只要被不可变数组赋值,此时都指向同一个内存地址。

NSMutable可变的类型最好不要使用copy,不可变的看需不需要被修改,在看strong 和 copy的定义。

你可能感兴趣的:(iOS 的strong和copy)