Subclasses must support the protocol and implement the copyWithZone: method. 子类必须遵从协议并且实现 copyWithZone: 方法. 除非是直接继承自 NSObject.子类在实现 copyWithZone: 必须先发送消息给 super 。 如果一个对象的类采用了NSCopying协议并且实现了它的copyWithZone:方法,那么这个对象就可以被拷贝。 However, copyWithZone: produces a shallow copy. 然而,copyWithZone: 产生的是一个浅拷贝,这种类型的深拷贝,是指对集合对象的进行深拷贝。集合里的对象依旧是浅拷贝。
copyWithZone(NSZone zone)方法是接口NSCopying提供的接口。 而因为这个接口存在于实现文件而不是头文件,所以它不是对外公开的;即是说外部无法直接调用copyWithZone(NSZone zone)方法。 copyWithZone(NSZone zone)方法是在上面所说的copy方法调用后再调用的,作用是将对象的所有数据都进行复制。 因此使用者需要在copyWithZone(NSZone zone)方法里做工作,而不是copy方法,这一点和Java的clone方法不同。 iOS SDK 和 JDK 中的应用 Objective-C中可以使用 协议,配合- (id)copyWithZone:(NSZone *)zone方法; 或者协议,配合 copyWithZone:/mutableCopyWithZone
大家可能会觉得疑惑,程序只是调用了copy和mutableCopy方法,为什么会提示找不到copyWithZone:与mutableCopyWithZone:方法呢? 其实当程序调用对象的copy方法来复制自身时,底层需要调用copyWithZone:方法来完成实际的复制工作,copy返回实际上就是copyWithZone:方法的返回值;mutableCopy与mutableCopyWithZone 2.让类实现copyWithZone:/mutableCopyWithZone:方法 所以让我们的Person类能够复制自身,我们需要让Person实现NSCopying协议;然后实现copyWithZone :方法时,其父类已经实现NSCopying协议,并重写过了copyWithZone:方法,那么子类重写copyWithZone:方法应先调用父类的copy方法复制从父类继承得到的成员变量,然后对子类中定义的成员变量进行赋值 : (id)copyWithZone:(NSZone *)zone { id obj = [super copyWithZone:zone]; //对子类定义的成员变量赋值 ...
standardPreferenceModel; <NSCopying> NSCoping好像没有什么快捷的方法, 只能一个一个copy 当类中包含其他类似, 其他类也实现NSCoping就行 - (id)copyWithZone _holderId; holder.choose = _choose; holder.avatar = [_avatar copy]; holder.gender = [_gender copyWithZone :zone]; holder.relation = [_relation copyWithZone:zone]; return holder; }
NSCopying协议中的声明的方法只有一个- (id)copyWithZone:(NSZone *)zone。 当我们的类实现了NSCopying协议,通过类的对象调用copy方法时,copy方法就会去调用我们实现的- (id)copyWithZone:(NSZone *)zone方法,实现拷贝功能。 实现代码如下所示: - (id)copyWithZone:(NSZone *)zone{ PersonModel *model = [[[self class] allocWithZone 所以,如果自定义类具有可变和不可变的区别,想让它支持拷贝时,就需要同时实现NSCopying和NSMutableCopying,在- (id)copyWithZone:(NSZone *)zone返回的是不可变对象 例如NSArray,在定义的时候需要申明支持NSCopying和NSMutableCopying协议,在NSArray中实现- (id)copyWithZone:(NSZone *)zone,在NSMutableArray
nullable instancetype)initWithCoder:(NSCoder *)aDecoder; 同时也建议对象实现NSCoping协议,该协议允许复制对象,遵循该协议要实现- (id)copyWithZone decodeObjectForKey:@"version"]; } return self; } 接下来是遵循了NSCopying协议的方法实现 #pragma mark NSCoping - (id)copyWithZone AddDeviceModel *copy = [[[self class] allocWithZone:zone] init]; copy.deviceType = [self.deviceType copyWithZone :zone]; copy.roomType = [self.roomType copyWithZone:zone]; copy.brand = [self.brand copyWithZone :zone]; copy.version = [self.version copyWithZone:zone]; return copy; } 特别注意 如果需要归档的类是某个自定义类的子类时
中单例实现步骤 1 在类的内部提供一个static修饰的全局变量 2 提供一个类方法,方便外界访问 3 重写+allocWithZone方法,保证永远都只为单例对象分配一次内存空间 4 严谨起见,重写-copyWithZone //return _instance; // 最好用self 用Tools他的子类调用时会出现错误 return [[self alloc]init]; } // 为了严谨,也要重写copyWithZone 和 mutableCopyWithZone -(id)copyWithZone:(NSZone *)zone { return _instance; } -(id)mutableCopyWithZone 单例实现步骤 1 在类的内部提供一个static修饰的全局变量 2 提供一个类方法,方便外界访问 3 重写+allocWithZone方法,保证永远都只为单例对象分配一次内存空间 4 严谨起见,重写-copyWithZone return _instance;\ }\ \ +(instancetype)share##name\ {\ return [[self alloc]init];\ }\ -(id)copyWithZone
属性的set方法是调用了新值的copy协议,也就是调用了NSMutableString的copyWithZone方法 4. NSMutableString的copyWithZone方法 Founation苹果并没有开源,所以需要别的途径。 在NSMutableString并没有找到对应的copyWithZone,继续向上找到父类NSString的copyWithZone。 copy修饰的NSString、NSArray、NSDictory类型变量,在进行Set方法时,会调用objc_setProperty函数,而最终会调用新值对应类型(NSMutableString)的copyWithZone
musicTool; } /** NSLog(@"%@",[[[HLMusicTool alloc]init] copy]);//Returns the object returned by copyWithZone copyWithZone 遵守协议NSCopying */ - (id)copyWithZone:(nullable NSZone *)zone{ return _musicTool; } musicTool; } /** NSLog(@"%@",[[[HLMusicTool alloc]init] copy]);//Returns the object returned by copyWithZone copyWithZone 遵守协议NSCopying */ - (id)copyWithZone:(nullable NSZone *)zone{ return _musicTool; } &onceToken, ^{ _dataTool = [super allocWithZone:zone]; }); return _dataTool; } - (id)copyWithZone
mutableCopy操作,生成新的可变对象 自定义类的实现copy(NSCopying协议) 若想令自己写的类具有copy功能,则需要实现NSCopying、NSMutableCopying协议 - (id)copyWithZone if (self) { _name = [name copy]; _price = price; } return self; } - (id)copyWithZone --%zd",p1,p1.name,p1.price); log: 0x60000002cce0--iPhone--999 0x6000000371c0--iPhone--999 注:在- (id)copyWithZone
如果用这种方式进行深copy,每一个object都会发送copyWithZone:方法。 CopyWithZone只会执行一层copy。 ii. unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray];] 几种Copy方法的甄别: a) CopyWithZone
0x600000c1da40 p1:0x600000c76c60 因为alloc会执行allocWithZone,所以如果想只分配一次内存就要重写此方法,同时为了严谨,防止copy出现以上问题,还要重写copyWithZone onceToken, ^{ _instance = [[super allocWithZone:zone]init]; }); return _instance; } -(id)copyWithZone &onceToken, ^{ \ _instance = [[super allocWithZone:zone]init]; \ }); \ return _instance; \ } \ -(id)copyWithZone
retain操作 只有不可变对象创建不可变副本(copy)才是浅复制,其他都是深复制 举例:对象的自定义拷贝 对象拥有复制特性,须实现NSCopying、NSMutabelCopying协议,实现该协议的copyWithZone 深浅拷贝的不同实现;代码示例 Objective - C 对象的深浅拷贝的区别就在于你对copyWithZone的不同实现 ?
oneToken, ^{ singleCase = [[super allocWithZone:NULL] init]; }); return singleCase; } - (id)copyWithZone struct _NSZone *)zone { return [SingleCase sharedSingleCase]; } // 防止copy 返回的还是同一个对象 + (id)copyWithZone
= [[super allocWithZone:zone] init]; } return single; } 4.为了防止用户把单例进行深浅拷贝,我们需要重写copyWithZone NSMutableCopying> //单例中获取单例对象的方法 +(id) getInstance; //单例测试方法 -(void) singletonFunction; @end 重写copyWithZone 方法 1 2 3 4 5 //为了防止通过copy来创建新的实例我们要重写copyWithZone; -(id)copyWithZone:(NSZone *)zone { return self
dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance; } -(id)copyWithZone onceToken, ^{ \ _instance = [[super allocWithZone:zone] init]; \ }); \ return _instance; \ } \ - (id)copyWithZone onceToken, ^{ \ _instance = [[super allocWithZone:zone] init]; \ }); \ return _instance; \ } \ - (id)copyWithZone
initWithCoder:(NSCoder *)aDecoder { self = [super init]; return [self yy_modelInitWithCoder:aDecoder]; } - (id)copyWithZone initWithCoder:(NSCoder *)aDecoder {\ self = [super init];\ return [self modelInitWithCoder:aDecoder];\}\- (id)copyWithZone
lastNameStr-BB lastNameStr-BB 自定义类的实现copy(NSCopying协议) 若想令自己写的类具有copy功能,则需要实现NSCopying、NSMutableCopying协议 - (id)copyWithZone if (self) { _name = [name copy]; _price = price; } return self; } - (id)copyWithZone --%zd",p1,p1.name,p1.price); log: 0x60000002cce0--iPhone--999 0x6000000371c0--iPhone--999 注:在- (id)copyWithZone
适当实现copyWithZone。 onceToken, ^{ _singleton = [[self alloc] init]; }); return _singleton; } - (id)copyWithZone
allocWithZone:(struct _NSZone *)zone 15 { 16 return [Singleton shareInstance] ; 17 } 18 19 -(id) copyWithZone