创建宏以执行默认初始化

时间:2013-03-23 13:43:49

标签: objective-c macros

我有很多方法可以重复这个简单的样板:

- (id)myObject {
    if(!_myObject) {
        self.myObject = [_myObject.class new];
    }
    return _myObject;
}

所以我想用一个简单的宏替换它:

#define default_init(instance) \
    if(!instance) instance = [instance.class new]; \
    return instance;

所以我只需要打电话:

- (id)myObject {
        default_init(_myObject);
}

上面的代码目前正在编译,但问题是宏直接设置了实例变量的值。相反,我想调用self.instance = value;

所以而不是

if(!instance) instance = [instance.class new];

我喜欢这样的东西;

if(!instance) self.instance = [instance.class new];

但显然目前的代码不允许这样做。我怎么能做到这样的事呢?

3 个答案:

答案 0 :(得分:1)

使用此宏:

#define default_init(class, instance)      \
    if ( ! _##instance ) {                 \
        self.instance = [class new] ;      \
    }                                      \
    return _##instance

我能够创建这个实例方法:

- (NSMutableArray*) myObject {
    default_init(NSMutableArray, myObject) ;
}

我必须添加一个定义类的参数,因为_myObject仍然是nil,因此_myObject.classnil

This StackOverflow questionthis Cprogramming page建议在do {...} while(0)中包装您的多行宏:

#define default_init(class, instance)          \
    do {                                       \
        if ( ! _##instance ) {                 \
            self.instance = [class new] ;      \
        }                                      \
        return _##instance ;                   \
    } while(0)

如果你真的想要,你可以创建一个定义整个方法的宏:

#define default_getter(class, instance)        \
    - (class*) instance {                      \
        if ( ! _##instance ) {                 \
            self.instance = [class new] ;      \
        }                                      \
        return _##instance ;                   \
    }

然后使用它:

default_getter(NSMutableArray, myObject)

答案 1 :(得分:0)

我通常声明属性:

而不是构建getter方法的宏

Instance.h

@interface Instance : NSObject
@property NSMutableArray* myObject ;
@end

并覆盖- init以初始化属性:

Instance.m

- (id) init {
    self = [super init] ;
    if ( self ) {
        self.myObject = [NSMutableArray new] ;
    }
    return self ;
}

答案 2 :(得分:0)

好的,这是我的看法。

注意:这样做只是为了看看是否可以完成。我认为在运输代码中使用它不是一个好主意。

首先从libextobjc导入#import "EXTRuntimeExtensions.h"。然后:

#define underize(name) _##name

#define property_type(property) \
    property_attr(property)->objectClass

#define property_attr(propertyName) \
    ext_copyPropertyAttributes(class_getProperty(self.class, # propertyName))

#define default_init(propertyName) \
    - (id)propertyName { \
       if(!underize(propertyName)) self.propertyName = [property_type(propertyName) new]; \
       return underize(propertyName); \
} \

然后说你有一个财产:

@property (nonatomic) NSArray *myArray;

你可以这样做:

default_init(myArray);

这会创建一个默认的getter。