在Objective-c中, 某個類遵守了NSCopying協議就代表這個類支持[obj copy]操作。在沒有實現NSCopying協議的情況下調用對象的copy函數則會出現異常。NSCopying協議只有一個函數,即copyWithZone, 聲明如下 :
@protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
@end
zone參數是新對象將分配到的內存區,一般不用修改。
遵守NSCopying協議則需要在@implementation中實現copyWithZone函數。
// Person
@interface Person : NSObject <NSCopying>
@property (nonatomic, copy) NSString* name;
@property int age ;
-(id) initWithName:(NSString*) pName andAge:(int) iAge ;
@end
Person類的實現。
// impl
@implementation Person
@synthesize name, age ;
//
-(id) initWithName:(NSString*) pName andAge:(int) iAge
{
self = [super init] ;
if ( self ) {
self.name = pName ;
self.age = iAge ;
}
return self ;
}
// 實現copyWithZone
-(id) copyWithZone:(NSZone *)zone
{
NSLog(@"Person copyWithZone, class : %@.", [self.class description]) ;
// 如果子類覆寫該方法, 則[self class]的類型為子類型,如果直接使用
// [[Person allocWithZone:zone] init], 則子類覆寫時會出錯.
Person* per = [[[self class] allocWithZone:zone] init] ;
per.name = self.name ;
per.age = self.age ;
return per ;
}
@end
// impl
@implementation Person
@synthesize name, age ;
//
-(id) initWithName:(NSString*) pName andAge:(int) iAge
{
self = [super init] ;
if ( self ) {
self.name = pName ;
self.age = iAge ;
}
return self ;
}
// 實現copyWithZone
-(id) copyWithZone:(NSZone *)zone
{
NSLog(@"Person copyWithZone, class : %@.", [self.class description]) ;
// 如果子類覆寫該方法, 則[self class]的類型為子類型,如果直接使用
// [[Person allocWithZone:zone] init], 則子類覆寫時會出錯.
Person* per = [[[self class] allocWithZone:zone] init] ;
per.name = self.name ;
per.age = self.age ;
return per ;
}
@end
在copyWithZone函數中創建了一個對象,並且將屬性挨個拷貝給新的對象。注意新對象per的創建方法是
[[[self class] allocWithZone:zone] init] ;
而不是
[[Person allocWithZone:zone] init] ;
這是因為如果有子類覆寫了copyWithZone函數,那麼在子類對象被拷貝時會調用Person類的copyWithZone函數, 如果硬編碼類型為Person, 則創建的對象為Person類型, 而不是子類型,因此會出現異常。而[self class]則會獲取正確的類型, 並且創建出正確的對象,避免異常出現。
例如Student類繼承自Person類。
// subclass, Student
@interface Student : Person
// 班級名
@property (nonatomic, copy) NSString* className ;
@end
// subclass, Student
@interface Student : Person
// 班級名
@property (nonatomic, copy) NSString* className ;
@end
Student的實現,覆寫copyWithZone函數。
// Student實現
@implementation Student
// 覆寫copyWithZone,
-(id) copyWithZone:(NSZone *)zone
{
// 1、先調用父類的copyWithZone函數
Student* per = [super copyWithZone:zone] ;
// 2、再設置className
per.className = self.className ;
NSLog(@"Student copyWithZone") ;
return per ;
}
@end
Objective-C中@property的所有屬性詳解 http://www.linuxidc.com/Linux/2014-03/97744.htm
Objective-C 和 Core Foundation 對象相互轉換的內存管理總結 http://www.linuxidc.com/Linux/2014-03/97626.htm
使用 Objective-C 一年後我對它的看法 http://www.linuxidc.com/Linux/2013-12/94309.htm
10個Objective-C基礎面試題,iOS面試必備 http://www.linuxidc.com/Linux/2013-07/87393.htm
Objective-C適用C數學函數 <math.h> http://www.linuxidc.com/Linux/2013-06/86215.htm