2015-09-05 53 views
1

在@interface中聲明的正常ivar是__strong默認值。在ARC下運行時添加__strong ivar

@interface XLPerson : NSObject { 
    NSString *name; // __strong default 
} 
@end 

現在,我創建上面的類在運行時:

Class XLPerson = objc_allocateClassPair([NSObject class], "XLPerson", 0); 
size_t size = sizeof(NSString*); 
class_addIvar(XLPerson, "name", size, log2(align), @encode(NSString*))); 
objc_registerClass(XLPerson); 

然而,命名爲 「名」 伊娃是不是__strong伊娃。
當我使用object_setIvar()時,Ivar不能保存newValue(它將在Autorelease Pool結束時解除分配)。

id person = [[XLPerson alloc] init]; 
Ivar ivar = class_getInstanceVariable(XLPerson, "name"); 

@autoreleasepool { 
    object_setIvar(person, ivar, [NSString [email protected]"Stack%@", @"Overflow"]); 
    // @"StackOverflow" will be deallocated. 
} 
NSLog(@"%@", object_getIvar(person, ivar)); 
// BAD_ACCESS *** -[CFString retain]: message sent to deallocated instance 0x1004002f0 

然後我找到兩個功能class_setIvarLayoutclass_setWeakIvarLayout,但沒有在Objective-C Runtime Reference任何有用的信息。

那麼,如何將__strong Ivar添加到我在運行時創建的類中?

回答

0

您需要設置伊娃佈局成類,你的情況(一個強大的伊娃):

class_setIvarLayout(class, (const uint8_t *)"\x01"); 

然後告訴運行時類是根據ARC管理:

static void fixup_class_arc(Class class) { 
    struct { 
     Class isa; 
     Class superclass; 
     struct { 
      void *_buckets; 
      uint32_t _mask; 
      uint32_t _occupied; 
     } cache; 
     uintptr_t bits; 
    } *objcClass = (__bridge typeof(objcClass))class; 

#if !__LP64__ 
#define FAST_DATA_MASK 0xfffffffcUL 
#else 
#define FAST_DATA_MASK 0x00007ffffffffff8UL 
#endif 

    struct { 
     uint32_t flags; 
     uint32_t version; 
     struct { 
      uint32_t flags; 
     } *ro; 
    } *objcRWClass = (typeof(objcRWClass))(objcClass->bits & FAST_DATA_MASK); 

#define RO_IS_ARR 1<<7 

    objcRWClass->ro->flags |= RO_IS_ARR; 
} 

說它後你的班級註冊,這是非常棘手的,也許不穩定,我寧願屬性,而不是Ivars。

我的博客關於中文link here