我正在经历和更换@synthesized(个体)锁定重量/该方法使用objc_msgSendSuper调用一个类方法
void _ThreadsafeInit(Class theClassToInit, void *volatile *theVariableItLivesIn, void(^InitBlock)(void))
{
//this is what super does :X
struct objc_super mySuper = {
.receiver = (id)theClassToInit,
.super_class = class_getSuperclass(theClassToInit)
};
id (*objc_superAllocTyped)(struct objc_super *, SEL, NSZone *) = (void *)&objc_msgSendSuper;
// id (*objc_superAllocTyped)(id objc_super, SEL, NSZone *) = (void *)&objc_msgSend;
do {
id temp = [(*objc_superAllocTyped)(&mySuper /*theClassToInit*/, @selector(allocWithZone:), NULL) init];//get superclass in case alloc is blocked in this class;
if(OSAtomicCompareAndSwapPtrBarrier(0x0, temp, theVariableItLivesIn)) { //atomic operation forces synchronization
if(InitBlock != NULL) {
InitBlock(); //only the thread that succesfully set sharedInstance pointer gets here
}
break;
}
else
{
[temp release]; //any thread that fails to set sharedInstance needs to clean up after itself
}
} while (*theVariableItLivesIn == NULL);
}
其中,而在无争议的情况下
一点更详细的显示出显著更好的性能随着这个小宏(借口差的格式化,这很简单)。为了允许在最初的零检查之后声明该块,看起来会帮助LLVM保持“已经初始化”的路径非常快。这是我唯一关心的。
#define ThreadsafeFastInit(theClassToInit, theVariableToStoreItIn, aVoidBlockToRunAfterInit) if(theVariableToStoreItIn == nil) { _ThreadsafeInitWithBlock(theClassToInit, (void *)&theVariableToStoreItIn, aVoidBlockToRunAfterInit); }
所以使用objc_superAllocTyped注释掉的部分(实际上是第一次使用[theClassToInit allocWithZone:NULL],这是绝对是最好的办法:))初步实现了它,直到我意识到这伟大的工作,大部分的单身在项目中重写了allocWithZone来返回单例方法...无限循环。所以我想通过使用objc_msgSendSuper应该快速排序,但我得到这个错误。
[51431:17c03] +[DataUtils allocWithZone:]: unrecognized selector sent to class 0x4f9584
似乎错误并没有被涉及到的实际问题,如...
(lldb) po 0x4f9584
$1 = 5215620 DataUtils
(lldb) print (BOOL)[$1 respondsToSelector:@selector(allocWithZone:)]
(BOOL) $2 = YES
所以我肯定失去了一些东西......我相比,装配由产生的[ super allocWithZone:NULL]方法在一个空的类中...几乎相同,除了被调用的函数有不同的名称(可能只是使用不同的符号,不知道,不能很好地阅读它)。
任何想法?我可以在超类上使用class_getClassMethod并直接调用IMP,但我试图合理地滥用运行时:)
不要这样做。只是...不。 –
那么恕我直言,没有人应该重写allocWithZone,但我们不能总是得到我们想要的。我有兴趣听到除了担心objective-c运行时(这是你的朋友)之外,为什么这是无效的原因。 – Steazy
因为这是无用的代码,无缘无故地与运行时混淆,而不是一个很好的理由。如果你告诉我们为什么你认为你需要这样做,也许我们可以建议一个更好的方法? –