1.实现协议
(一)声明协议:
@protocol NSCopying -(id)copyWithZone:(NSZone *)zone; @end
@protocol NSCoding -(void)encodeWithCoder:(NSCoder *)aCoder; -(id)initWithCoder:(NSCoder *)aDecoder; @end
@protocol 告诉编译器:下面将是一个新的正式协议。
@protocol 之后是协议名称,协议名称唯一
然后是方法声明列表,协议的每个采用者都必须实现这些方法。
@end 结束符
使用协议步引入新的实例变量。
(二)采用协议
@interface Car : NSObject<NSCoding,NSCopying> { //实例变量 } //方法 @end
采用某个协议,在类的声明中列出该协议的名称,并用 < > 将协议名称括起来。
多个协议只见用逗号隔开,顺序步影响。
(三)实现协议
采用该协议的类的实现文件中,实现协议的声明的 v方法。
1).可以使用一下方法来检查一个对象是否遵守某个协议
if(![receiver conformsToProtocol:@protocol(MyXMLSupport)])
3).协议中的方法可从超累中继承,但并不意味着对于该子类,这些方法得到了正确的实现。当子类新增数据成员时???
2.常用协议
@protocol NSCopying
@protocol NSCoding
把对象编码为数据块,并保存在磁盘中。能将数据块读回到内存中。还能机遇保存的数据创建新的对象。
3.NSCopying协议
实质:
实现一个无实例变量类的复制,
即实现copy协议中的copyWithZone方法;
里程1:Engine类的复制
@interface Engine : NSObject<NSCopying> { //实例变量 } //方法 @end
因为用了NSCopying协议,必须实现它的方法。
@implementation Engine -(id)copyWithZone:(NSZone *)zone { Engine *engineCopy; engineCopy = [[[self class]allocWithZone:zone]init]; /** 实现过程: step1:[self class] 获取self对象所属的类。//向获取类就要发送class方法 step2:[[self class]allocWithZone:zone] 向该类发allocWithZone:zone消息,以分配内存并创建该类的一个新对象。//allocWithZone:zone使一个类消息step3: 向心对象发送init消息,以使其初始化。 **/ return engineCopy;}@endengineCopy = [[Engine allocWithZone:zone]init];在子类继承的时候会出错。
协议分为声明/使用/实现。可能三个同时出现,可能仅出现最后一个。
4.深拷贝和浅拷贝
浅层复制 (shallow copy)不复制引用对象,新复制的对象只指向现有的引用对象。
深层复制(deep copy)将复制所有引用的对象。
1).遵守NSCopying协议的类才可以发送copy消息;
2).遵守NSMutableCopying协议的类才可以发送mutablecopy消息
3).一个类没有遵守上述两个协议,而发送copy,mutablecopy,会发生异常。
里程2:Tire类的复制
//有实例变量,切其子类又新添加实例变量的类的复制 @interface Tire : NSObject<NSCopying> { float pressure; float threadDepth; } @property float pressure; @property float threadDepth; -(id)initWithPressure:(float)pressure; -(id)initWiththreadDepth:(float)threadDepth; -(id)initWithPressure:(float)pressure WiththreadDepth:(float)threadDepth; @end实现文件:@implementation Tire -(id)copyWithZone:(NSZone *)zone { Tire *tireCopy; tireCopy = [[[self class]allocWithZone:zone]initWithPressure:20.0f WiththreadDepth:20.0f]; /** 实现过程: step1:[self class] 获取self对象所属的类。 step2:[[self class]allocWithZone:zone] 向该类发allocWithZone:zone消息,以分配内存并创建该类的一个新对象。 step3: 向心对象发送initWithPressure: WiththreadDepth:消息,以使其初始化。也可以使用见大init。 **/ return tireCopy; } @endzone 来自方法参数,pressure和threaddepth 来自与类的成员变量。里程4:
allweather的复制
@interface allWeathRadical : Tire { float rain; float snow; } @property float rain; @property float snow; @end @implementation allWeathRadical -(id)copyWithZone:(NSZone *)zone { allWeathRadical *tireCopy; tireCopy = [super copyWithZone:zone]; [tireCopy setRain:rain]; [tireCopy setSnow:snow]; /** step1:tireCopy = [super copyWithZone:zone]; 调用超累的copyWithZone:zone方法 step2: [tireCopy setRain:rain]; [tireCopy setSnow:snow]; 调用访问器方法处理新增的实例变量 step3: 若子类无新增的实例变量,则可直接使用超类的协议方法,若新增,则需重写初始化方法。 **/ return tireCopy; }
里程4.实现car类的复制
实质:数据成员是指向oc对象的指针,调用协议方法,copy操作后内存管理方法。
在默认情况下,NSObject没有遵守这两个协议,但copy,mutable copy方法是nsobject定义的。
若要自定义copy,必须遵守nscopying协议,并实现copywithzone:方法
mutablecopy同上
遵守nscopying协议的基本是基础核心类,如nsstring,nsnumber;
copy后,返回一个新对象,程序员要负责释放,原先被拷贝对象的retaincount +1,所以不需要释放。
copy后,返回的是不能修改的对象,mutable copy返回的对象可能是可以修改的。
copy复制一个步可变对象。而mutable copy复制一个可变对象。
代码实例1:对非容器类对象的拷贝
1)。对一个不可变对象的复制,copy是指针复制,即浅拷贝;mutablecopy则是对象复制,即深拷贝。(实例1)
2)。对可变对象复制,都是深拷贝,但copy复制返回的对象是不可变的。(实例2)
代码实例2:对容器类本身
上面的结论也适用。
对容器而言,其元素对象事中是指针复制。如要元素对象的为对象复制,就需要实现深拷贝。
理解协议三步骤:声明协议/实现协议/使用协议
了解常用协议
理解深复制,浅复制
利用nscopying协议实现自定义objc对象的深复制。
了解nscopying协议对基础核心类对象的深/浅复制。