网站建设资质备案,sem是什么职业岗位,如何免费注册网址,周口航迪科技网站建设公司怎么样前言 copy#xff1a;需要先实现 NSCopying 协议#xff0c;创建的是不可变副本。mutableCopy#xff1a;需要实现 NSMutableCopying 协议#xff0c;创建的是可变副本。浅拷贝#xff1a;指针拷贝#xff0c;源对象和副本指向的是同一个对象。对象的引用计数器 #xf…前言 copy需要先实现 NSCopying 协议创建的是不可变副本。mutableCopy需要实现 NSMutableCopying 协议创建的是可变副本。浅拷贝指针拷贝源对象和副本指向的是同一个对象。对象的引用计数器 1其实相当于做了一次 retain 操作。深拷贝内容拷贝源对象和副本指向的是两个不同的对象。源对象引用计数器不变副本计数器设置为 1。只有不可变对象创建不可变副本copy才是浅拷贝其它都是深拷贝。在 iOS 中并不是所有的对象都支持 copymutableCopy遵守 NSCopying 协议的类可以发送 copy 消息遵守 NSMutableCopying 协议的类才可以发送 mutableCopy 消息。假如发送了一个没有遵守上 诉两协议而发送 copy 或者 mutableCopy那么就会发生异常。但是默认的 iOS 类并没有遵守这两个协议。如果想自定义一下 copy 那么就必须遵守 NSCopying并且实现 copyWithZone: 方法如果想自定义一下 mutableCopy 那么就必须遵守 NSMutableCopying并且实现 mutableCopyWithZone: 方法。copy 是创建一个新对象retain 是创建一个指针引用对象计数加 1。copy 属性表示两个对象内容相同新的对象 retain 为 1 与旧有对象的引用计数无关旧有对象没有变化。copy 减少对象对上下文的依赖。retain 属性表示两个对象地址相同建立一个指针指针拷贝内容当然相同这个对象的 retain 值 1 也就是说retain 是指针拷贝copy 是内容拷贝。1、系统的非容器类对象 /*系统的非容器类对象指的是 NSStringNSNumber 等等一类的对象。对于系统的非容器类对象如果对一不可变对象复制copy 是指针复制浅拷贝mutableCopy 就是对象复制深拷贝。如果是对可变对象复制都是深拷贝但是 copy 返回的对象是不可变的。*/NSString *string origion;NSString *stringCopy [string copy];NSMutableString *mstringMCopy [string mutableCopy];NSLog(%p, string);NSLog(%p, stringCopy); // 地址与 string 相同NSLog(%p, mstringMCopy); // 地址与 string 不同NSLog(%zi, [string retainCount]); // 引用计数为 2NSLog(%zi, [stringCopy retainCount]); // 引用计数为 2NSLog(%zi, [mstringMCopy retainCount]); // 引用计数为 1NSLog(%, stringCopy); // 内容与 string 相同NSLog(%, mstringMCopy); // 内容与 string 相同[mstringMCopy appendString:!!]; // mstringMCopy 是可变的NSLog(%, mstringMCopy);/*string 和 stringopy 指向的是同一块内存区域(又叫 apple 弱引用 weak reference)此时 stringCopy 的引用计数和 string 的一样都为。而 mstringMCopy 则是我们所说的真正意义上的复制系统为其分配了新内存但指针所指向的字符串还是和 string 所指的一样。*/NSMutableString *mstring [NSMutableString stringWithString: origion];NSString *stringCopy [mstring copy];NSMutableString *mStringCopy [mstring copy];NSMutableString *mstringMCopy [mstring mutableCopy];NSLog(%p, mstring);NSLog(%p, stringCopy); // 地址与 string 不同NSLog(%p, mStringCopy); // 地址与 string 不同与 stringCopy 相同NSLog(%p, mstringMCopy); // 地址与 string 不同NSLog(%, mstring);NSLog(%, stringCopy); // 内容与 string 相同NSLog(%, mStringCopy); // 内容与 string 相同NSLog(%, mstringMCopy); // 内容与 string 相同[mstring appendString: origion!];// [mStringCopy appendString:mm]; // errormStringCopy 不可变[mstringMCopy appendString:!!]; // mstringMCopy 可变NSLog(%, mstring);NSLog(%, mstringMCopy);/* 以上四个 NSString 对象所分配的内存都是不一样的。但是对于 mStringCopy 其实是个不可变对象所以上述会报错。*/ 2、系统的容器类对象 /*系统的容器类对象指 NSArrayNSDictionary 等。对于容器类本身上面讨论的结论也是适用的需要探讨的是复制后容器内对象的变化。对于系统的容器类对象copy 返回不可变对象是指针复制包括里面的元素也是指向相同的指针。mutablecopy 返回可变对象是对象复制其中容器内的元素内容都是指针复制可以改变其内的元素。*/NSArray *array [NSArray arrayWithObjects:a, b, c, nil];NSArray *arrayCopy [array copy];NSMutableArray *mArrayMCopy [array mutableCopy];NSLog(%p, array);NSLog(%p, arrayCopy); // 地址与 array 相同NSLog(%p, mArrayMCopy); // 地址与 array 不同NSLog(%zi,[array retainCount]);NSLog(%zi,[arrayCopy retainCount]);NSLog(%zi,[mArrayMCopy retainCount]);NSLog(%, array);NSLog(%, arrayCopy); // 内容与 array 相同NSLog(%, mArrayMCopy); // 内容与 array 相同[mArrayMCopy addObject:de]; // mArrayMCopy 可变NSLog(%, array);NSLog(%, mArrayMCopy);[mArrayMCopy removeObjectAtIndex:0];NSLog(%, array);NSLog(%, mArrayMCopy);/*copy 返回不可变对象mutablecopy 返回可变对象arrayCopy 是指针复制而 mArrayMCopy 是对象复制。arrayCopy 是和 array 同一个 NSArray 对象指向相同的对象包括 array 里面的元素也是指向相同的指针。mArrayMCopy 是 array 的可变副本指向的对象和 array 不同但是其中的元素和 array 中的元素指向的是同一个对象。mArrayMCopy 还可以改变其内的元素删除或添加。但是注意的是容器内的元素内容都是指针复制。*/NSArray *array [NSArray arrayWithObjects:[NSMutableString stringWithString:a], b, c, nil];NSArray *arrayCopy [array copy];NSMutableArray *mArrayMCopy [array mutableCopy];NSLog(%p, array);NSLog(%p, arrayCopy); // 地址与 array 相同NSLog(%p, mArrayMCopy); // 地址与 array 不同NSLog(%zi,[array retainCount]);NSLog(%zi,[arrayCopy retainCount]);NSLog(%zi,[mArrayMCopy retainCount]);NSLog(%, array);NSLog(%, arrayCopy); // 内容与 array 相同NSLog(%, mArrayMCopy); // 内容与 array 相同NSMutableString *testString [array objectAtIndex:0];[testString setString:1a1]; // 这样会改变 testString 的指针其实是将 “1a1” 临时对象赋给了 testString。这样以上三个数组的首元素都被改变了。NSLog(%, array);NSLog(%, arrayCopy); // 内容与 array 相同NSLog(%, mArrayMCopy); // 内容与 array 相同/*arrayCopymArrayMCopy 和 array 指向的都是不一样的对象但是其中的元素都是一样的对象同一个指针。对于容器而言其元素对象始终是指针复制。如果需要元素对象也是对象复制就需要实现深拷贝。*/NSArray *array [NSArray arrayWithObjects:[NSMutableString stringWithString:first], b, c, nil];NSArray *deepCopyArray [[NSArray alloc] initWithArray:array copyItems: YES];// 使用归档/反归档拷贝NSArray *trueDeepCopyArray [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject: array]]; NSLog(%, array);NSLog(%, deepCopyArray); // 内容与 array 相同NSLog(%, trueDeepCopyArray); // 内容与 array 相同NSMutableString *testString1 [array objectAtIndex:0];[testString1 setString:1a1];NSLog(%, array);NSLog(%, deepCopyArray); // 内容与 array 不同NSLog(%, trueDeepCopyArray); // 内容与 array 不同/*trueDeepCopyArray 是完全意义上的深拷贝而 deepCopyArray 则不是对于 deepCopyArray 内的不可变元素其还是指针复制。或者我们自己实现深拷贝的方法。因为如果容器的某一元素是不可变的那你复制完后该对象仍旧是不能改变的因此只需要指针复制即可。除非你对容器内的元素重新赋值否则指针复制即已足够。举个例子[[array objectAtIndex:0] appendstring:”sd”] 后其他的容器内对象并不会受影响。[[array objectAtIndex:1] 和 [[deepCopyArray objectAtIndex:1] 尽管是指向同一块内存但是我们没有办法对其进行修改——因为它是不可改变的。所以指针复制已经足够。所以这并不是完全意义上的深拷贝但是 apple 的官方文档将其列为 deep copy 了并添加了 copy 和 mutablity 的关系说明。*/ 3、自定义对象 需要自己要实现 NSCopyingNSMutableCopying 这样就能调用 copy 和 mutablecopy 了。 // Teacher.h// 遵守 NSCopying, NSMutableCopying 协议interface Teacher : NSObject NSCopying, NSMutableCopyingproperty (nonatomic, copy) NSString *name;property (nonatomic, assign) int age;end// Teacher.mimplementation Teacher// 实现协议方法委托方会自动调用协议中的该方法- (id)copyWithZone:(NSZone *)zone{Teacher *copy [[Teacher allocWithZone:zone] init];copy.name self.name;copy.age self.age;return copy;}// 实现协议方法委托方会自动调用协议中的该方法- (id)mutableCopyWithZone:(NSZone *)zone{Teacher *copy [[Teacher allocWithZone:zone] init]; copy.name self.name;copy.age self.age;return copy;}- (NSString *)description{return [NSString stringWithFormat:% %i, self.name, self.age];}end// main.m#import Teacher.hTeacher *tch [[Teacher alloc] init];tch.name xiao xin;tch.age 28;// 内容复制Teacher *tchCpy [tch copy];// 内容复制Teacher *tchMCopy [tch mutableCopy];tchCpy.age 20;tchMCopy.age 22;NSLog(%p, tch);// tchCpy 与 tch 的地址不同NSLog(%p, tchCpy);// tchMCopy 与 tch 的地址不同NSLog(%p, tchMCopy);NSLog(%, tch);// tchCpy 与 tch 的实例变量的值不同NSLog(%, tchCpy);// tchMCopy 与 tch 的实例变量的值不同NSLog(%, tchMCopy);// Children.h// 遵守 NSCopying, NSMutableCopying 协议interface Children : NSObject NSCopying, NSMutableCopyingproperty (nonatomic, copy) NSString *name;property (nonatomic, assign) int age;end// Children.mimplementation Children// 实现协议方法委托方会自动调用协议中的该方法。- (id)copyWithZone:(NSZone *)zone{// 若有类继承此类并且此方法在子类中可用id copy [[[self class] allocWithZone:zone] init];[copy setName:self.name];[copy setAge:self.age];return copy;}// 实现协议方法委托方会自动调用协议中的该方法。- (id)mutableCopyWithZone:(NSZone *)zone{// 若有类继承此类并且此方法在子类中可用id copy [[[self class] allocWithZone:zone] init];[copy setName:self.name];[copy setAge:self.age];return copy;}end// GoodChildren.hinterface GoodChildren : Childrenproperty (nonatomic, assign)int score;end// GoodChildren.mimplementation GoodChildren// 实现协议方法委托方会自动调用协议中的该方法。- (id)copyWithZone:(NSZone *)zone{ GoodChildren *copy [super copyWithZone:zone];copy.score self.score;return copy;}// 实现协议方法委托方会自动调用协议中的该方法。- (id)mutableCopyWithZone:(NSZone *)zone{ GoodChildren *copy [super copyWithZone:zone];copy.score self.score;return copy;}- (NSString *)description{return [NSString stringWithFormat:% %i %d, self.name, self.age, self.score];}end// main.m#import GoodChildren.hGoodChildren *gChild [[GoodChildren alloc] init];gChild.name xiao xin;gChild.age 18;gChild.score 88;// 内容复制GoodChildren *gChildCopy [gChild copy];// 内容复制GoodChildren *gChildMCopy [gChild mutableCopy];gChildCopy.age 20;gChildMCopy.age 22;gChildCopy.score 100;gChildMCopy.score 120;NSLog(%p, gChild);// gChildCopy 与 gChild 的地址不同NSLog(%p, gChildCopy);// gChildMCopy 与 gChild 的地址不同NSLog(%p, gChildMCopy);NSLog(%, gChild);// gChildCopy 与 gChild 的实例变量的值不同NSLog(%, gChildCopy);// gChildMCopy 与 gChild 的实例变量的值不同NSLog(%, gChildMCopy); 转载于:https://www.cnblogs.com/QianChia/p/5782887.html