1.復制可變字符串
[objc] view plaincopy
- NSMutableString * city = [NSMutableString stringWithString:@"北京"];
- //復制可變副本
- NSMutableString * cityCopy = [city mutableCopy];
- //修改副本
- [cityCopy replaceCharactersInRange:NSMakeRange(0, 2) withString:@"臨滄"];
- //輸出看到原字符串沒有改變 當前的改變
- NSLog(@"原來的city是%@,現在的cityCopy是%@",city,cityCopy);
2.復制不可變字符串的可變副本
[objc] view plaincopy
- NSString * str =@"測試的字符串";
- NSMutableString * strCopy = [str mutableCopy];
- //增加字符串
- [strCopy appendString:@"再加一段字符串"];
- NSLog(@"strCopy是是%@",strCopy);
- //為可變字符串返回一個不可變副本
- NSMutableString * cityCopy2 = [city copy];
- //由於city是不可變的下面的代碼是錯誤的
- [cityCopy2 appendString:@"這樣是錯的"];
報錯信息
// 2015-05-05 17:19:37.988 copyDemo[424:303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with appendString:'
// *** First throw call stack:
總結 復制的時候返回的字符串是否可變與原來的字符串或是復制時給予的類型沒有關系。主要取決於調用了copy方法還是mutableCopy方法。
3.對象拷貝
對於自定義的對象我們需要實現NSCopying和NSMutableCopying
[objc] view plaincopy
- @interface Person : NSObject
- @property(nonatomic,strong)NSMutableString *name;
- @property(nonatomic,assign)int age;
- @end
[objc] view plaincopy
- #import "Person.h"
- @interface Person()<NSCopying>
- @end
- @implementation Person
- - (id)copyWithZone:(NSZone *)zone{
- Person * person = [[[self class] allocWithZone:zone] init];
- person.name = self.name;
- person.age = self.age;
- return person;
- }
- @end
[objc] view plaincopy
- #import <Foundation/Foundation.h>
- #import "Person.h"
- int main(int argc, const charchar * argv[]) {
- @autoreleasepool {
- Person * person = [Person new];
- person.name = [NSMutableString stringWithString:@"小明"];
- person.age = 20;
- Person * personCopy = [person copy];//復制副本
- personCopy.name = [NSMutableString stringWithString:@"小強"];
- personCopy.age =23;
- NSLog(@"person的名字是%@",person.name);
- NSLog(@"person的n年齡是%d",person.age);
- NSLog(@"personCopy的名字是%@",personCopy.name);
- NSLog(@"personCopy的年齡是%d",personCopy.age);
- // 2015-05-05 17:38:43.980 copyDemo[531:303] person的名字是小明
- // 2015-05-05 17:38:43.981 copyDemo[531:303] person的n年齡是20
- // 2015-05-05 17:38:43.981 copyDemo[531:303] personCopy的名字是小強
- // 2015-05-05 17:38:43.982 copyDemo[531:303] personCopy的年齡是23
- }
- return 0;
- }
4.淺拷貝
其他不變修改main函數
[objc] view plaincopy
- Person * person = [Person new];
- person.name = [NSMutableString stringWithString:@"小明"];
- person.age = 20;
- Person * personCopy = [person copy];//復制副本
- [personCopy.name replaceCharactersInRange:NSMakeRange(0,2) withString:@"變了嘛"];
- personCopy.age =23;
- NSLog(@"person的名字是%@",person.name);
- NSLog(@"person的n年齡是%d",person.age);
- NSLog(@"personCopy的名字是%@",personCopy.name);
- NSLog(@"personCopy的年齡是%d",personCopy.age);
打印出來的是
2015-05-05 17:54:05.347 copyDemo[563:303] person的名字是變了嘛
2015-05-05 17:54:05.349 copyDemo[563:303] person的n年齡是20
2015-05-05 17:54:05.350 copyDemo[563:303] personCopy的名字是變了嘛
2015-05-05 17:54:05.350 copyDemo[563:303] personCopy的年齡是23
一開始我也很迷惑。差距只有一句代碼而已。不過還是有差別的。
原因就在
[objc] view plaincopy
- person.name = self.name;
- person.age = self.age;
name是一個指針變量,存放的只是字符串地而已。所以說修改了拷貝的name,原來的name也會發生改變,使用personCopy.name = [NSMutableString stringWithString:@"小強"];這句代碼的話其實是直接重新賦值,指向了另外一個字符串指針,所以拷貝的對象修改了。原來的並沒有改變。但是並不代表拷貝的時候不指向一個字符串。只是後來被修改了。
5.深拷貝
將copyWithZone方法裡面的修改
[objc] view plaincopy
- person.name = [self.name mutableCopy];
- person.age = self.age;
這樣就實現了深復制。
但是一般情況下,深復制難度比較大。尤其是有很多指針的時候,Fundation一般都是淺復制。
6.setetr方法的復制
修改如下代碼
[objc] view plaincopy
- @property(nonatomic,copy)NSMutableString *name;
修改main
[objc] view plaincopy
- Person * person = [Person new];
- person.name = [NSMutableString stringWithString:@"小明"];
- //下面這行代碼會報錯的。
- [person.name appendString:@"會報錯了"];
name的屬性使用了copy指示符的話其實相當於setNmame方法裡面
[objc] view plaincopy
- - (void)setName(NSString *)name{
- name = [name copy];
- }
是對參數的一個不可變拷貝