NSString用copy修饰的原因

一言以蔽之:为了安全!

当一个可变字符串(NSMutableString)赋值给一个字符串属性(无论这个字符串是NSString还是NSMutableString),

如果此属性是retain修饰的,就是浅拷贝,引用计数加1。赋值后源字符串改变,这个属性值也跟着改变。

如果此属性是copy修饰的,就是深拷贝,引用计数等于1(因为从堆里新分配一个内存块)。赋值后源字符串改变,这个属性值不会改变。(保证了安全)

假设对象有下面4个属性:

1 @property (retain, nonatomic) NSString *retainStr;
2 @property (copy, nonatomic)   NSString *copyStr;
3 @property (retain, nonatomic) NSMutableString *retainMStr;
4 @property (copy, nonatomic)   NSMutableString *copyMStr;
 1     NSMutableString *mStr = [NSMutableString string];
 2
 3     [mStr setString:@"我没变-------"];
 4     self.retainStr   = mStr;  // 浅拷贝,引用计数加1,
 5     NSLog(@"%ld",[self.retainStr retainCount]);// 2
 6
 7     self.copyStr     = mStr;    // 深拷贝,
 8     NSLog(@"%ld",[self.copyStr retainCount]);// 1
 9
10     self.retainMStr = mStr;   // 浅拷贝,引用计数加1,
11     NSLog(@"%ld",[self.retainMStr retainCount]);// 3
12
13     self.copyMStr   = mStr;   // 深拷贝
14     NSLog(@"%ld",[self.copyMStr retainCount]);// 1
15
16
17
18     NSLog(@"retainStr:%@",  self.retainStr);
19     NSLog(@"copyStr:%@",    self.copyStr);
20     NSLog(@"retainMStr:%@", self.retainMStr);
21     NSLog(@"copyMStr:%@",   self.copyMStr);
22
23     NSLog(@"\n");
24
25     [mStr setString:@"我变了--------"];
26
27     NSLog(@"retainStr:%@",  self.retainStr);// 浅拷贝
28     NSLog(@"%ld",[self.retainStr retainCount]);// 3
29
30     NSLog(@"copyStr:%@",    self.copyStr);// 深拷贝
31     NSLog(@"%ld",[self.copyStr retainCount]);// 1
32
33     NSLog(@"retainMStr:%@", self.retainMStr);// 浅拷贝
34     NSLog(@"%ld",[self.retainMStr retainCount]);// 3
35
36     NSLog(@"copyMStr:%@",   self.copyMStr);// 深拷贝
37     NSLog(@"%ld",[self.copyMStr retainCount]);// 1
38
39     NSLog(@"\n");

当一个不可变字符串(NSString)赋值给一个字符串属性(无论这个字符串是NSString还是NSMutableString),就不存在安全性问题,都是深拷贝。此时无论retain还是copy都无所谓。

 1     NSString *str = @"我来了";//[[NSString alloc] initWithString:@"我来了"];//两种方式都一样。都在常量区
 2
 3     self.retainStr  = str;
 4     self.copyStr    = str;
 5     self.retainMStr = [str mutableCopy];
 6     self.copyMStr   = [str mutableCopy];
 7
 8     NSLog(@"retainStr:%@",  self.retainStr);
 9     NSLog(@"copyStr:%@",    self.copyStr);
10     NSLog(@"retainMStr:%@", self.retainMStr);
11     NSLog(@"copyMStr:%@",   self.copyMStr);
12
13     NSLog(@"\n");
14
15     str =@"我走了";//[[NSStringalloc] initWithString:@"我走了"];//两种方式都一样
16
17     NSLog(@"retainStr:%@",  self.retainStr);
18     NSLog(@"copyStr:%@",    self.copyStr);
19     NSLog(@"retainMStr:%@", self.retainMStr);
20     NSLog(@"copyMStr:%@",   self.copyMStr);
21
22     NSLog(@"\n");

打印结果如下:

1 2016-06-16 12:24:36.818 OCLession9[5278:90728] retainStr:我来了
2 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyStr:我来了
3 2016-06-16 12:24:36.819 OCLession9[5278:90728] retainMStr:我来了
4 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyMStr:我来了
5 2016-06-16 12:24:36.819 OCLession9[5278:90728]
6 2016-06-16 12:24:36.819 OCLession9[5278:90728] retainStr:我来了
7 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyStr:我来了
8 2016-06-16 12:24:36.819 OCLession9[5278:90728] retainMStr:我来了
9 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyMStr:我来了
时间: 2024-11-03 21:16:09

NSString用copy修饰的原因的相关文章

针对NSString的copy修饰前后,引用计数的变化

1 NSLog(@"NSString的对象,用NSString来接---------------------------------"); 2 NSString *string1 = [[NSString alloc]initWithFormat:@"不可变字符串"]; 3 NSLog(@"copy前,不可变字符串的引用计数 = %ld", [string1 retainCount]); 4 5 NSString *copyString1 = s

iOS之NSString类型为什么要用copy修饰

在开发的过程中,只知道NSString类型最好用copy修饰而不能用strong,但是不知道为什么,今天了解了下,总算搞明白了. 如下所示,当修饰符为copy时,因为NSMutableString是NSString类型的子类,所以可以用指针self.name指向mStr,但是我们知道copy的含义是指当重新赋值时深拷贝新对象再赋值给self.name, 所以此时self.name的指针和mStr的指针指向的对象就不同了,所以当给mStr对象发送方法appendString的时候,修改的只是mSt

关于NSArray使用时用strong修饰还是copy修饰问题测试

大家都知道,使用NSMutableArray时是用strong修饰,例如: [objc] view plain copy @property (nonatomic,strong) NSMutableArray * mutableArray; 但是,NSArray呢?我看大多数人都直接使用strong,而且网上还有很多人说除了NSString用copy,其他对象类型都用strong. 那么,问题来了:当用strong修饰NSArray的时候,如果遇到用可变数组给它赋值怎么办?会导致意料之外的bug

静态成员函数不能采用const修饰的原因

静态成员函数不能用const修饰 ,也不能存取nonstatic数据 C++中静态成员函数不能用const修饰的原因: static在c++中的第五种含义:用static修饰不访问非静态数据成员的类成员函数.这意味着一个静态成员函数只能访问它的参数.类的静态数据成员和全局变量. 不能用const的原因:一个静态成员函数访问的值是其参数.静态数据成员和全局变量,而这些数据都不是对象状态的一部分.而对成员函数中使用关键字const是表明:函数不会修改该函数访问的目标对象的数据成员.既然一个静态成员函

深拷贝和浅拷贝以及NSString的copy retain

浅拷贝就比如像引用类型,而深拷贝就比如值类型. 浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同).对其中任何一个对象的改动都会影响另外一个对象.举个例子,一个人一开始叫张三,后来改名叫李四了,可是还是同一个人,不管是张三缺胳膊少腿还是李四缺胳膊少腿,都是这个人倒霉. 深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响.举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会

iOS内存管理(4)--Block属性用copy修饰 & 避免循环引用的问题

一.Block的类型 根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock. NSGlobalBlock:类似函数,位于text段: NSStackBlock:位于栈内存,函数返回后Block将无效: NSMallocBlock:位于堆内存. 二.Block的copy.retain.release操作 不同于NSObjec的copy.retain.release操作: Block_copy与copy等效,Block_relea

NSString为何要用copy修饰,而不是strong?

NSString本身是无所谓的,但是如果一个 NSString 指针指向了一个 NSMutableString的内存空间的话,如果使用 strong 修饰的话,如果你在别处修改这个值的话,那么原来的值也会改变.用 copy 是生成了一份新的内存空间,所以原值不会改变. 所以用copy是为了安全,防止NSMutableString赋值给NSString时,前者修改引起后者值变化而用的.

NSString NSMutableString copy mutableCopy retain weak strong

NSString 与 NSMutableString NSString是不可变字符串对象,这句话的意思,结合代码: #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSString *str = @"Shaw"; NSString *str1 = @"Root"; // NSString *str1的意思是str1

block要用copy修饰,还是用strong

栈区与堆区 block本身是像对象一样可以retain,和release.但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上.他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃.使用retain也可以,但是block的retain行为默认是用copy的行为实现的, 因为block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的