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);
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
Then I find two functions class_setIvarLayout
and class_setWeakIvarLayout
, but there is not any useful information in Objective-C Runtime Reference
.
So, how can I add a __strong Ivar into my class created at runtime?
You need to set ivar layouts into class, in your case (a single strong ivar):
then tell runtime your class is managed under ARC:
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