objective-c - 如何在 Objective-C 中创建可重用的类级属性构造?

标签 objective-c cocoa metaprogramming

我想要拥有类级别的属性,我从 https://stackoverflow.com/a/15811719/157384 找到了解决方案

@interface Model
+ (int) value;
+ (void) setValue:(int)val;
@end

@implementation Model
static int value;
+ (int) value
{ @synchronized(self) { return value; } }
+ (void) setValue:(int)val
{ @synchronized(self) { value = val; } }
@end

现在您可以通过属性访问器进行调用,如下所示:

Model.value = 1
Model.value // => 1

太棒了!

现在,我想以某种形式的宏或元编程使这段代码可重用,它需要属性名称和类型。怎么写呢?

在上面的示例中,value(int)(以及 Model)应该是动态的。

更新

感谢@Rich,我现在有了这个:

// Common.h
#define CLASS_PROPERTY_INTERFACE(TYPE, METHOD, CMETHOD) \
+ (TYPE) METHOD; \
+ (void) set##CMETHOD:(TYPE)val; \

#define CLASS_PROPERTY_IMPLEMENTATION(TYPE, METHOD, CMETHOD) \
static TYPE _##METHOD; \
+ (TYPE) METHOD \
{ @synchronized(self) { return _##METHOD; } } \
+ (void) set##CMETHOD:(TYPE)val \
{ @synchronized(self) { _##METHOD = val; } } \

// User.h
@interface User : NSObject
CLASS_PROPERTY_INTERFACE(User *, me, Me)
@end

// User.m
@implementation User
CLASS_PROPERTY_IMPLEMENTATION(User *, me, Me)
@end

User.me = currentUser;
User.me // => currentUser

剩下要做的一件事是,如果可能的话,自动将传递给宏的方法名称大写。

但它已经比现有的样板简洁得多了!

最佳答案

宏观方式...

注意: 这有点可怕,我真的不建议使用它,但正在尝试在宏中定义它们......

需要注意的是(除了它不太“好”之外),setter 方法的格式为 set_XXX: 格式。

#define CLASS_INTERFACE(CLS_NAME, METHOD, TYPE) @interface CLS_NAME : NSObject \
    + (TYPE) METHOD; \
    + (void) set_##METHOD:(TYPE)val; \
    @end \

#define CLASS_IMPLEMENTATION(CLS_NAME, METHOD, TYPE) @implementation CLS_NAME \
    static TYPE METHOD; \
    + (TYPE) METHOD \
    { @synchronized(self) { return METHOD; } } \
    + (void) set_##METHOD:(TYPE)val \
    { @synchronized(self) { METHOD = val; } } \
    @end \

将以下内容放入头文件中:

CLASS_INTERFACE(Test, value, int)

.m 文件中:

CLASS_IMPLEMENTATION(Test, value, int)

然后使用Test类:

[Test set_value:4];
int i = [Test value];

同样,这非常可怕,但会起作用......!

编辑:

使用单例

正如评论中提到的,我认为使用单例更好,这使我编写了更可怕的代码:(

现在我们已经(准备好病袋):

#define SINGLETON_INTERFACE_START(CLS_NAME) @interface CLS_NAME : NSObject \
    +(instancetype) sharedInstance; \

#define SINGLETON_INTERFACE_END(CLS_NAME) \
    @end \
    static inline CLS_NAME * CLS_NAME##Global () { return [CLS_NAME sharedInstance]; }

#define SINGLETON_IMPLEMENTATION(CLS_NAME) @implementation CLS_NAME \
    +(instancetype) sharedInstance \
    { \
        static id instance; \
        static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
            instance = [self new]; \
        }); \
        return instance; \
    } \
    @end \

在你的标题中:

SINGLETON_INTERFACE_START(Test)

@property (atomic, assign) NSUInteger value;

SINGLETON_INTERFACE_END(Test)

在你的.m中:

SINGLETON_IMPLEMENTATION(Test)

并使用它(是的,可以产生更多的病):

TestGlobal().value = 1;
int i = TestGlobal().value;

或者“更好的”Objective-C 方式:

[Test sharedInstance].value = 1;
int i = [Test sharedInstance].value;

您甚至可以(美国队现在生病了)为界面中的属性设置一个#define

请注意,我已将 @interface 中的 @property 定义保留为 atomic,因为 OP 似乎喜欢使用 @同步。这是不需要的,因为它们被设置为atomic

我知道OP想要类“属性”(只是说这让我颤抖),但还有其他更好选择!

关于objective-c - 如何在 Objective-C 中创建可重用的类级属性构造?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23279603/

相关文章:

iphone - Objective-C 中的内存管理

cocoa - 读取 Cocoa 中的音频输入电平峰值

c++ - 由具有不同数量参数的其他函数参数化的函数模板

iphone - “Live”UITableView - 从服务器获取小部分数据

objective-c - 启动应用后模态视图不出现

ios - 从 iOS 应用程序与 Facebook 分享超链接

swift - 使用 PDFOutline 将 TOC 添加到 Swift/Cocoa 中的 PDFDocument

objective-c - NSDateFormatter 在样式和格式之间交换

C++ 类型特征

ruby-on-rails - 要扩展 Rails 的 `link_to` ,我应该使用 `alias_method_chain` 还是混合 + 继承?