In my project there is a class which has many variables, now I want it to conform to NSCopying
protocol, so I have to "copy" every variable in - (id)copyWithZone:(NSZone *)zone
. If the variable is a object, send copy to it, if it is a scalar value, just use assignment symbol.
The class may change frequently, which means I may add some variables afterwards, then I or somebody else may forget to modify the code in - (id)copyWithZone:(NSZone *)zone
method. To avoid it, I'm thinking about to use objective-c's runtime feature to do the work.
Below is a part of the Class, the variables in the class are ether a object or a scalar value. You will notice an array of unsigned int, it is an exception, you can omit it because I can manually copy it when the type encoding of variable is [10I]
.
@interface DataObject : NSObject <NSCopying>
{
@public
unsigned int arrPrice[10];
}
@property (nonatomic, copy) NSString *code ;
@property (nonatomic, assign) unsigned char type ;
@property (nonatomic, assign) int digit ;
@property (nonatomic, assign) unsigned int count ;
@property (nonatomic, assign) unsigned short time ;
@property (nonatomic, assign) char season ;
@property (nonatomic, assign) int64_t amount ;
@property (nonatomic, strong) NSMutableArray *mArray ;
@property (nonatomic, assign) BOOL isOk ;
@end
And the copyWithZone:
- (id)copyWithZone:(NSZone *)zone
{
DataObject *obj = [[DataObject allocWithZone:zone] init] ;
unsigned int uVarCount = 0 ;
Ivar *pVarList = class_copyIvarList(self.class, &uVarCount) ;
for (unsigned int i = 0; i < uVarCount; ++i) {
Ivar *pVar = pVarList+i ;
const char *name = ivar_getName(*pVar) ;
const char *typeEncoding = ivar_getTypeEncoding(*pVar) ;
NSString *strTypeEncoding = [NSString stringWithUTF8String:typeEncoding] ;
if ([strTypeEncoding isEqualToString:@"[I10]"]) {
// its arrPrice, use memcpy to copy
memcpy(obj->arrPrice, self->arrPrice, sizeof(arrPrice)) ;
continue ;
} else if ([strTypeEncoding hasPrefix:@"@"]) {
// its a object
id o = object_getIvar(self, *pVar) ;
o = [o copy] ;
object_setIvar(obj, *pVar, o) ;
NSLog(@"var name:%s, type:%s, value:%@", name, typeEncoding, o) ;
} else {
// runtime error
id o = object_getIvar(self, *pVar) ;
object_setIvar(obj, *pVar, o) ;
}
}
free(pVarList) ;
return obj ;
}
I get runtime error when the variable is not an object and I find why, but I don't know how to solve it.