2

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

- (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];

但显然当前的代码不允许这样做。我怎么能完成这样的事情?

4

3 回答 3

1

使用此宏:

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

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

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

我必须添加一个定义类的参数,因为_myObjectis still nil,因此_myObject.classis nil

这个 StackOverflow 问题这个 Cprogramming 页面建议将您的多行宏包装在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)
于 2013-03-23T16:04:03.937 回答
0

我通常不使用宏来构建 getter 方法,而是声明属性:

实例.h

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

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

实例.m

- (id) init {
    self = [super init] ;
    if ( self ) {
        self.myObject = [NSMutableArray new] ;
    }
    return self ;
}
于 2013-03-23T16:36:17.373 回答
0

好的,这是我的看法。

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

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

#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。

于 2013-03-23T16:45:59.573 回答