本文介绍了在ARC下在运行时添加__strong ivar的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在@interface中声明的普通ivar是__strong默认值.

A normal ivar declared in @interface is __strong default.

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

现在,我在运行时创建上述类:

Now, I create above class at runtime:

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);

但是,名为"name"的ivar不是__strong ivar.
当我使用object_setIvar()时,Ivar无法保存newValue(它将在自动释放池的末尾释放).

However, the ivar named "name" isn't a __strong ivar.
While I using object_setIvar(), the Ivar can't hold the newValue (it will be deallocated at the end of Autorelease Pool).

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

@autoreleasepool {
   object_setIvar(person, ivar, [NSString stringWithFormat@"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中没有任何有用的信息.

Then I find two functions class_setIvarLayout and class_setWeakIvarLayout, but there is not any useful information in Objective-C Runtime Reference.

那么,如何在运行时创建的类中添加__strong Ivar?

So, how can I add a __strong Ivar into my class created at runtime?

推荐答案

在您的情况下,您需要将ivar布局设置为类(单个强ivar):

You need to set ivar layouts into class, in your case (a single strong ivar):

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

然后告诉运行时您的班级是在ARC下管理的:

then tell runtime your class is managed under 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.

Call it after your class's registering, this is very tricky and maybe unstable, I would prefer properties rather than ivars.

有关此内容的中文博客,在此处链接

My blog about this in Chinese, link here

这篇关于在ARC下在运行时添加__strong ivar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-13 22:13