NSString
@property (nonatomic , strong) NSString * strongString;
@property (nonatomic , copy) NSString * mCopyString;
NSMutableString * tempStr = [[NSMutableString alloc] init];
[tempStr appendFormat:@"test"];
self.strongString = tempStr;
self.mCopyString = tempStr;
NSLog(@"strongString %p %@",self.strongString,self.strongString);
NSLog(@"mCopyString %p %@",self.mCopyString,self.mCopyString);
[tempStr appendFormat:@"change"];
NSLog(@"strongString %p %@",self.strongString,self.strongString);
NSLog(@"mCopyString %p %@",self.mCopyString,self.mCopyString);
以下是打印结果
2017-11-19 16:52:30.307674+0800 test[4346:378408] strongString 0x600000256b60 test
2017-11-19 16:52:30.307840+0800 test[4346:378408] mCopyString 0xa000000747365744 test
2017-11-19 16:52:30.307943+0800 test[4346:378408] strongString 0x600000256b60 testchange
2017-11-19 16:52:30.308060+0800 test[4346:378408] mCopyString 0xa000000747365744 test
结论: NSString 是不可变字符串,修饰的时候应该用 copy 修饰,这样它的值不会发生改变
NSMutableString
//如果这样修饰会出现什么问题呢?
@property (nonatomic , copy) NSMutableString * mCopyString;
self.mCopyString = [[NSMutableString alloc] init];
[self.mCopyString appendFormat:@"test"];
会这样报错
2017-11-19 16:58:24.268556+0800 test[4403:382549] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with appendFormat:'
*** First throw call stack:
借着这个例子我们说下 copy
copy:建立一个引用计数为1的对象,然后释放原有对象;常常用于NSString/NSArray/NSDictionary(不可变)。在赋值时传入值的一份拷贝,拷贝工作由copy方法执行
其实这里给 NSString 进行赋值的对象是 NSString 那就和 strong 是一样的,如下:
@property (nonatomic , copy) NSString * mCopyString;
NSString * tempStr = @"test";
NSLog(@"%p %@",tempStr,tempStr);
self.mCopyString = tempStr;
NSLog(@"%p %@",self.mCopyString,self.mCopyString);
2017-11-19 17:10:12.655578+0800 test[4507:390294] 0x1016d4098 test
2017-11-19 17:10:12.655740+0800 test[4507:390294] 0x1016d4098 test
如果是可变的,就会 copy 一份
@property (nonatomic , copy) NSString * mCopyString;
NSMutableString * tempStr = [[NSMutableString alloc] init];
[tempStr appendFormat:@"test"];
NSLog(@"%p %@",tempStr,tempStr);
self.mCopyString = tempStr;
NSLog(@"%p %@",self.mCopyString,self.mCopyString);
2017-11-19 17:07:55.904637+0800 test[4490:388984] 0x60400045c7d0 test
2017-11-19 17:07:55.904808+0800 test[4490:388984] 0xa000000747365744 test
NSArray
@property (nonatomic , copy) NSArray * mCopyArray;
@property (nonatomic , strong) NSArray * mStrongArray;
NSArray * mArray = @[@"1",@"2"];
NSLog(@"mArray %p %@",mArray,mArray);
self.mCopyArray = mArray;
NSLog(@"self.mCopyArray %p %@",self.mCopyArray,self.mCopyArray);
NSMutableArray * mMutableArray = [[NSMutableArray alloc] init];
[mMutableArray insertObject:@"1" atIndex:0];
NSLog(@"mMutableArray %p %@",mMutableArray,mMutableArray);
self.mCopyArray = mMutableArray;
NSLog(@"self.mCopyArray %p %@",self.mCopyArray,self.mCopyArray);
[mMutableArray insertObject:@"2" atIndex:0];
NSLog(@"self.mCopyArray %p %@",self.mCopyArray,self.mCopyArray);
NSMutableArray * mStrongArray = [[NSMutableArray alloc] init];
[mStrongArray insertObject:@"1" atIndex:0];
NSLog(@"mStrongArray %p %@",mStrongArray,mStrongArray);
self.mStrongArray = mStrongArray;
NSLog(@"self.mStrongArray %p %@",self.mStrongArray,self.mStrongArray);
[mStrongArray insertObject:@"2" atIndex:0];
NSLog(@"self.mStrongArray %p %@",self.mStrongArray,self.mStrongArray);
打印结果
2017-11-19 17:19:04.207782+0800 test[4664:398783] mArray 0x60400003a720 (
1,
2
)
2017-11-19 17:19:04.208416+0800 test[4664:398783] self.mCopyArray 0x60400003a720 (
1,
2
)
2017-11-19 17:19:04.208703+0800 test[4664:398783] mMutableArray 0x604000252a50 (
1
)
2017-11-19 17:19:04.210955+0800 test[4664:398783] self.mCopyArray 0x604000009650 (
1
)
2017-11-19 17:19:04.211328+0800 test[4664:398783] self.mCopyArray 0x604000009650 (
1
)
2017-11-19 17:19:04.211413+0800 test[4664:398783] mStrongArray 0x604000252bd0 (
1
)
2017-11-19 17:19:04.211483+0800 test[4664:398783] self.mStrongArray 0x604000252bd0 (
1
)
2017-11-19 17:19:04.211551+0800 test[4664:398783] self.mStrongArray 0x604000252bd0 (
2,
1
)
结论: NSArray 使用 copy 修饰时,如果赋值对象是不可变数组,那么相当于直接 retain , 如果是 可变数组 , 那么会 copy 一份并且 retain
但是 NSArray 如果使用 strong 赋值,那么,可能会出现一些 bug: 如果赋值对象是可变数组, 可变数组改变了值, NSArray 也会一样改变
NSMutableArray
@property (nonatomic , copy) NSMutableArray * mMutableArray;
self.mMutableArray = [[NSMutableArray alloc] init];
[self.mMutableArray insertObject:@"1" atIndex:0];
2017-11-19 17:23:45.441256+0800 test[4682:401433] -[__NSArray0 insertObject:atIndex:]: unrecognized selector sent to instance 0x600000007e80
(lldb)
结论: NSMutableArray 需要使用 strong 修饰
NSDictionary
同理 NSArray
@property (nonatomic , copy) NSDictionary * mCopyDictionary;
@property (nonatomic , strong) NSDictionary * mStrongDictionary;
NSDictionary * mDict = @{@"xiaoli":@"123"};
NSLog(@"mDict %p %@",mDict,mDict);
self.mCopyDictionary = mDict;
NSLog(@"self.mCopyDictionary %p %@",self.mCopyDictionary,self.mCopyDictionary);
NSMutableDictionary * mMutableDict = [[NSMutableDictionary alloc] init];
[mMutableDict setObject:@"456" forKey:@"xiaowang"];
NSLog(@"mMutableArray %p %@",mMutableDict,mMutableDict);
self.mCopyDictionary = mMutableDict;
NSLog(@"self.mCopyArray %p %@",self.mCopyDictionary,self.mCopyDictionary);
[mMutableDict setObject:@"789" forKey:@"xiaoming"];
NSLog(@"self.mCopyArray %p %@",self.mCopyDictionary,self.mCopyDictionary);
NSMutableDictionary * mStrongDict = [[NSMutableDictionary alloc] init];
[mStrongDict setObject:@"xiaoli" forKey:@"125"];
NSLog(@"mStrongArray %p %@",mStrongDict,mStrongDict);
self.mStrongDictionary = mStrongDict;
NSLog(@"self.mStrongArray %p %@",self.mStrongDictionary,self.mStrongDictionary);
[mStrongDict setObject:@"xiaoli" forKey:@"999"];
NSLog(@"self.mStrongArray %p %@",self.mStrongDictionary,self.mStrongDictionary);
2017-11-19 17:32:04.841820+0800 test[4728:406099] mDict 0x60000003eda0 {
xiaoli = 123;
}
2017-11-19 17:32:04.842005+0800 test[4728:406099] self.mCopyDictionary 0x60000003eda0 {
xiaoli = 123;
}
2017-11-19 17:32:04.842179+0800 test[4728:406099] mMutableArray 0x60400003dd80 {
xiaowang = 456;
}
2017-11-19 17:32:04.842351+0800 test[4728:406099] self.mCopyArray 0x604000230e00 {
xiaowang = 456;
}
2017-11-19 17:32:04.842500+0800 test[4728:406099] self.mCopyArray 0x604000230e00 {
xiaowang = 456;
}
2017-11-19 17:32:04.842631+0800 test[4728:406099] mStrongArray 0x60000003efe0 {
125 = xiaoli;
}
2017-11-19 17:32:04.842737+0800 test[4728:406099] self.mStrongArray 0x60000003efe0 {
125 = xiaoli;
}
2017-11-19 17:32:04.842842+0800 test[4728:406099] self.mStrongArray 0x60000003efe0 {
125 = xiaoli;
999 = xiaoli;
}
结论: NSDictronary 用 copy 修饰
NSMutableDictronary
@property (nonatomic , copy) NSMutableDictionary * mMutableDict;
self.mMutableDict = [[NSMutableDictionary alloc] init];
[self.mMutableDict setObject:@"xiaoli" forKey:@"123"];
2017-11-19 17:34:57.436056+0800 test[4746:407822] -[__NSFrozenDictionaryM setObject:forKey:]: unrecognized selector sent to instance 0x60000003a980
(lldb)
结论: NSMutableDictionary 用 strong 修饰