gpt4 book ai didi

objective-c - 如何为不采用 NSCopying 的类制作对象实例的副本?

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

在某些情况下(例如,当 Hook 到内部进行测试时)能够创建不采用 NSCopying 的类实例的副本会很方便(不要实现 -copyWithZone:).如何实现? (注意:在类别中实现协议(protocol)是不够的,因为并非所有类的实例变量都在其 header 中可见。)

我尝试遍历对象的 Ivar,并且 (1) 对于对象类型递归(或保留),以及,(2) 对于基本类型,获取 ivar 的地址原始实例和正在制作的副本,memcpy缓冲区从源 ivar 的地址开始到目标 ivar 的地址。

@interface NSObject (ADDLCopy)

- (id)addl_generateCopyDeep:(BOOL)deepCopy;

@end

@implementation NSObject (ADDLCopy)

//modified from http://stackoverflow.com/a/12265664/1052673
- (void *)addl_ivarPointerForName:(const char *)name
{
void *res = NULL;

Ivar ivar = class_getInstanceVariable(self.class, name);

if (ivar) {
res = (void *)self + ivar_getOffset(ivar);
}

return res;
}


- (id)addl_generateCopyDeep:(BOOL)deepCopy;
{
id res = [[self.class alloc] init];

unsigned int count = 0;
Ivar *ivars = class_copyIvarList(self.class, &count);
for (unsigned int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
//We need to try here because of a bug with NSGetSizeAndAlignment
//which prevents bitfields from being handled properly and results
//in an exception being thrown. See this link for more discussion:
//http://lists.apple.com/archives/cocoa-dev/2008/Sep/msg00883.html
@try {
NSUInteger size = 0;
const char *encoding = ivar_getTypeEncoding(ivar);
NSGetSizeAndAlignment(encoding, &size, NULL);
char firstEncodingCharacter[2];
strncpy(firstEncodingCharacter, encoding, 1);
firstEncodingCharacter[1] = 0;
if (strcmp(firstEncodingCharacter, "@") == 0) {
if (deepCopy) {
id original = object_getIvar(self, ivar);
id copy = [original addl_generateCopyDeep:deepCopy];
object_setIvar(res, ivar, copy);
} else {
id original = object_getIvar(self, ivar);
object_setIvar(res, ivar, original);
}
} else {
const char *name = ivar_getName(ivar);
void *bytesSource = [self addl_ivarPointerForName:name];
void *bytesTarget = [res addl_ivarPointerForName:name];
memcpy(bytesTarget, bytesSource, size);
}
}
@catch (NSException *exception) {}
@finally {}
}
free(ivars);

return res;
}

@end

这有点管用,但有几个我知道的明显问题,更不用说那些我不知道的问题了。首先,它不复制从父类(super class)继承的ivars。其次,它不适用于集合。另外,由于a bug in NSGetSizeAndAlignment ,它不适用于位掩码。此外,它没有考虑关联的对象。

如何递归复制一个对象的实例(以及它拥有的所有对象)?如果这不是完全可能的(处理保留并存储在 void 指针中的拥有对象即使可能也相当困难),可以做到什么程度?

最佳答案

简而言之,你不能。

“深度”复制是一个非常特定领域的问题。

例如,你是复制一个对象的 delegate 还是让副本的 delegate 指向同一个对象(或者你是否将它设置为 nil并要求复制客户端设置)?

对于那个例子,与复制相关的每上下文业务逻辑还有无数其他一次性位(这就是为什么“深度复制”的概念没有在集合类上实现的原因)。

以上所有假设您实际上拥有实现细节。对于在框架中实现的类,无法安全地复制它们,因为根本没有可用的数据甚至不知道需要复制哪些内存位,更不用说如何复制了。

您需要限制复制操作的范围和定义,然后寻求解决方案。

关于objective-c - 如何为不采用 NSCopying 的类制作对象实例的副本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15825281/

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