2015-09-05 6 views
1

Обычный ivar, объявленный в @interface, является значением __strong по умолчанию.добавить __strong ivar во время выполнения под ARC

@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).

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_setIvarLayout и class_setWeakIvarLayout, но нет никакой полезной информации в Objective-C Runtime Reference.

Итак, как я могу добавить __strong Ivar в свой класс, созданный во время выполнения?

ответ

0

Вы должны установить Ивар макеты в класс, в вашем случае (один сильный Ивар):

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

то сказать во время выполнения вашего класса управляется под АРК:

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