gpt4 book ai didi

objective-c - 如何使用 objective-c 运行时复制实例

转载 作者:搜寻专家 更新时间:2023-10-30 20:27:57 26 4
gpt4 key购买 nike

在我的项目中有一个有很多变量的类,现在我希望它符合 NSCopying 协议(protocol),所以我必须“复制” - (id)copyWithZone 中的每个变量:(NSZone *)zone.如果变量是一个对象,则将副本发送给它,如果它是一个标量值,则只需使用赋值符号。

类可能会经常更改,这意味着我可能会在之后添加一些变量,然后我或其他人可能会忘记修改 - (id)copyWithZone:(NSZone *)zone 方法中的代码。为了避免这种情况,我正在考虑使用 objective-c 的运行时功能来完成这项工作。

下面是类的一部分,类中的变量是一个对象或标量值。你会注意到一个unsigned int数组,它是一个异常(exception),你可以省略它,因为当变量的类型编码是[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

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 ;
}

当变量不是对象时出现运行时错误,我发现 why , 但我不知道如何解决。

最佳答案

首先:在 OOP 中,复制是一个复杂的问题,通用的 90% 解决方案通常不是什么好主意。然而,……

如果你有一个非对象引用属性(NSIntegerdoublestruct 等等),你必须使用-object_getInstanceVariable ()。但事情可能更复杂。

让我们先试试:

   } else {
long *valuePointer;
object_getInstanceVariable(self, ivar_getName(pVar), & valuePointer) ;
object_setInstanceVariable(obj, ivar_getName(pVar), valuePointer) ;
}

如您所见,我使用了一个指向long 的指针。如果属性类型是 long,这是合法的。 (对于与 long 大小相同的所有其他类型可能都是合法的。)关于其他类型,尤其是 struct 类型,你不能这样做,因为它们可以有不同的尺寸。因此,要获得完整的解决方案,您必须分析编码字符串。

至少在这一点上,您应该重新考虑一下,通用副本是否是个好主意。我更喜欢 not 分支。

关于objective-c - 如何使用 objective-c 运行时复制实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30588306/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com