Nat*_*ler 3 objective-c objective-c-runtime
在某些上下文中(例如,当挂钩到内部进行测试时),能够创建不采用NSCopying(不实现-copyWithZone:)的类的实例的副本将是方便的.怎么能实现这一目标?(注意:在类别中实现协议是不够的,因为并非所有类的实例变量都在其标题中可见.)
我已经试过遍历对象的Ivars和(1)对象类型递归(或保留),和(2)的基本类型,获得在原有的实例化而这正在取得和拷贝伊娃的地址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
Run Code Online (Sandbox Code Playgroud)
这有点作用,但我知道有几个明显的问题,更不用说那些我不知道的问题了.首先,它不会复制从超类继承的ivars.其次,它不适用于收藏.另外,由于存在错误NSGetSizeAndAlignment,它不适用于位掩码.此外,它无法考虑关联的对象.
如何递归复制对象的实例(以及它拥有的所有对象)?如果这不是完全可能的(如果可能的话,处理保留并存储在void指针中的拥有对象似乎相当困难),它可以在多大程度上完成?
总之,你不能.
"深度"复制是一个极其特定于域的问题.
例如,您是复制delegate对象还是delegate将副本指向同一对象(或者将其设置为nil并要求复制客户端设置它)?
对于那个例子,与复制相关的每个上下文业务逻辑有大量其他一次性位(这就是为什么"深度复制"的概念没有在集合类上实现的原因).
以上所有假设您实际上都有实现细节.对于在框架中实现的类,没有办法安全地复制它们,因为根本没有可用的数据甚至不知道需要复制哪些内存位,更不用说如何了.
您需要限制复制操作的范围和定义,然后寻求解决方案.
| 归档时间: |
|
| 查看次数: |
374 次 |
| 最近记录: |