一当纱、為什么@property聲明(NString坡氯,NSArray箫柳,NSDictionary)時(shí)需要使用copy滞时,使用strong有什么問題坪稽。
- 因?yàn)镹String窒百,NSArray篙梢,NSDictionary都有自己對(duì)應(yīng)的子類:NSMutableString渤滞,NSMutableArray,NSMutableDictionary绪励,而父類指針可以指向子類對(duì)象疏魏,使用copy可以讓本對(duì)象不受外界(子對(duì)象)影響大莫,無論給我傳入的是一個(gè)可變對(duì)象還是一個(gè)不可變對(duì)象,都能保證自身持有的是一個(gè)不可變副本懈凹。
- 使用strong時(shí)介评,如果這個(gè)屬性指向一個(gè)可變對(duì)象寒瓦,修改可變對(duì)象時(shí)杂腰,這個(gè)屬性值也會(huì)被修改。
舉例說明:
定義兩個(gè)屬性string和array用strong修飾
@interface ViewController ()
@property (strong, nonatomic) NSString *string;
@property (strong, nonatomic) NSArray *array;
@end
@implementation ViewController
- (void)viewDidLoad {
NSMutableString * mString = [NSMutableString stringWithString:@"123"];
self.string = mString;
[mString appendString:@"666"];
NSLog(@"%@",self.string);
NSMutableArray *mArray = [NSMutableArray arrayWithObjects:@1,@2,@3, nil];
self.array = mArray;
[mArray addObject:@6];
NSLog(@"%@",self.array);
}
打印結(jié)果:
2017-06-02 17:43:22.440 測試Test[45671:7372719] 123666
2017-06-02 17:43:22.441 測試Test[45671:7372719] (
1,
2,
3,
6
)
這里的屬性string和array分別被賦值子類可變對(duì)象mString和mArray,再分別修改mString和mArray導(dǎo)致string和array都被修改了漓帅。
下面看看使用copy關(guān)鍵字后的結(jié)果:(所有代碼不變忙干,只是strong改成copy)
打印結(jié)果:
2017-06-02 17:48:32.583 測試Test[45795:7380495] 123
2017-06-02 17:48:32.583 測試Test[45795:7380495] (
1,
2,
3
)
屬性string和array都沒有被修改。所以使用copy能保證屬性不被子類對(duì)象修改時(shí)同時(shí)被修改。
二暇韧、深拷貝和淺拷貝
- 深拷貝:內(nèi)容的拷貝
- 淺拷貝:地址的拷貝
1浓瞪、對(duì)非集合對(duì)象的copy和mutableCopy
- (void)viewDidLoad {
[super viewDidLoad];
NSString *string = @"123";
NSString *stringCopy = [string copy];
NSLog(@"string的地址:%p,stringCopy的地址:%p",string,stringCopy);
NSMutableString *stringMCopy = [string mutableCopy];
NSLog(@"stringMCopy的地址:%p",stringMCopy);
NSMutableString * mString = [NSMutableString stringWithString:@"123"];
NSString *mStringCopy = [mString copy];
NSLog(@"mString的地址:%p,mStringCopy的地址:%p",mString,mStringCopy);
NSMutableString *mStringMCopy = [mString mutableCopy];
NSLog(@"mStringMCopy的地址:%p",mStringMCopy);
}
打印結(jié)果:
2017-06-03 10:22:58.643 測試Test[61063:7767634] string的地址:0x10d696078,stringCopy的地址:0x10d696078
2017-06-03 10:22:58.644 測試Test[61063:7767634] stringMCopy的地址:0x61000006a640
2017-06-03 10:22:58.644 測試Test[61063:7767634] mString的地址:0x61000006d040,mStringCopy的地址:0xa000000003332313
2017-06-03 10:22:58.644 測試Test[61063:7767634] mStringMCopy的地址:0x600000072200
2乾颁、對(duì)集合對(duì)象的copy和mutableCopy
集合對(duì)象指的是NSArray,NSDictionary湾盒,NSSet等類的對(duì)象毅人。
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *array = @[@1, @2, @3, @4];
NSArray *arrayCopy = [array copy];
NSMutableArray *arrayMCopy = [array mutableCopy];
NSLog(@"array的地址:%p,arrayCopy的地址:%p,arrayMCopy的地址:%p",array,arrayCopy,arrayMCopy);
NSMutableArray *mArray = [NSMutableArray arrayWithObjects:@1, @2, @3, @4, nil];
NSArray *mArrayCopy = [mArray copy];
NSMutableArray *mArrayMCopy = [mArray mutableCopy];
NSLog(@"mArray的地址:%p,mArrayCopy的地址:%p,mArrayMCopy的地址:%p",mArray,mArrayCopy,mArrayMCopy);
}
打印結(jié)果:
2017-06-03 10:50:14.247 測試Test[61941:7806421] array的地址:0x600000058090,arrayCopy的地址:0x600000058090,arrayMCopy的地址:0x600000057b50
2017-06-03 10:50:14.247 測試Test[61941:7806421] mArray的地址:0x6100000556c0,mArrayCopy的地址:0x610000055780,mArrayMCopy的地址:0x610000055870
可以得出結(jié)論集合對(duì)象的copy和mutableCopy和非集合對(duì)象相同的結(jié)果:
- [immutableObject copy]是淺拷貝
- [immutableObject mutableCopy]是深拷貝
- [mutableObject copy]是深拷貝
- [mutableObject mutableCopy]是深拷貝
注意事項(xiàng):
集合對(duì)象的深拷貝只是對(duì)象本身缔俄,而集合對(duì)象的元素還是地址的拷貝邀桑,即單層深拷貝:
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *mArray1 = [NSMutableArray arrayWithObjects:@2, @2, @3, @4, nil];
NSArray *array = @[mArray1, @2, @3, @4];
NSArray *arrayCopy = [array copy];
NSMutableArray *arrayMCopy = [array mutableCopy];
NSLog(@"array的地址:%p,arrayCopy的地址:%p,arrayMCopy的地址:%p",array,arrayCopy,arrayMCopy);
NSMutableArray *mArray = [NSMutableArray arrayWithObjects:mArray1, @2, @3, @4, nil];
NSArray *mArrayCopy = [mArray copy];
NSMutableArray *mArrayMCopy = [mArray mutableCopy];
NSLog(@"mArray的地址:%p,mArrayCopy的地址:%p,mArrayMCopy的地址:%p",mArray,mArrayCopy,mArrayMCopy);
NSLog(@"array的第一個(gè)元素地址:%p,arrayMCopy的第一個(gè)元素地址:%p",array[0],arrayMCopy[0]);
NSLog(@"mArray的第一個(gè)元素地址:%p,mArrayMCopy的第一個(gè)元素地址:%p",mArray[0],mArrayMCopy[0]);
}
打印結(jié)果:
2017-06-03 11:08:52.382 測試Test[62621:7832878] array的地址:0x618000054c70,arrayCopy的地址:0x618000054c70,arrayMCopy的地址:0x618000054cd0
2017-06-03 11:08:52.382 測試Test[62621:7832878] mArray的地址:0x600000056020,mArrayCopy的地址:0x600000055fc0,mArrayMCopy的地址:0x600000056080
2017-06-03 11:08:52.383 測試Test[62621:7832878] array的第一個(gè)元素地址:0x6180000548e0,arrayMCopy的第一個(gè)元素地址:0x6180000548e0
2017-06-03 11:08:52.383 測試Test[62621:7832878] mArray的第一個(gè)元素地址:0x6180000548e0,mArrayMCopy的第一個(gè)元素地址:0x6180000548e0
三令杈、block為什么要使用copy
block使用copy是在MRC中延續(xù)下來的跌榔,在MRC下僧须,方法內(nèi)部的block如果有被copy屬性修飾纲刀,且捕獲了外部變量担平,那么他會(huì)被copy到堆上;如果被assgin修飾的空另,且捕獲了外部變量,那么他是stack_block摄杂,是在棧上的;如果僅僅只是一個(gè)copy的屬性的block析恢,么有捕獲外部變量,它還是是global_block,它是在全局區(qū)泽篮。
在ARC下編譯器會(huì)自動(dòng)對(duì)block進(jìn)行copy柑船,因此我們使用copy或者strong修飾的效果是一樣的。但是我們?cè)贏RC下繼續(xù)使用copy可以提醒我們編譯器會(huì)自動(dòng)幫我們實(shí)現(xiàn)copy的操作亏拉。至于block是哪中類型的逆巍,他是在內(nèi)存的哪個(gè)區(qū)的锐极,和MRC下的是一樣的,要看block有木有引用外部變量肋层。