可以使用 Objective-C 的关联对象 API 添加属性( 支持存储)。我什至为此目的编写了一个小宏。但在宏之前,它看起来像“展开”:
#import <objc/runtime.h>
@interface UIViewController (SOAdditions)
@property (atomic, readwrite, copy) NSString* myProperty;
@end
static void * const kMyPropertyAssociatedStorageKey = (void*)&kMyPropertyAssociatedStorageKey;
@implementation UIViewController (SOAdditions)
- (void)setMyProperty:(NSString *)myProperty
{
objc_setAssociatedObject(self, kMyPropertyAssociatedStorageKey, myProperty, OBJC_ASSOCIATION_COPY);
}
- (NSString*)myProperty
{
return objc_getAssociatedObject(self, kMyPropertyAssociatedStorageKey);
}
@end
您可以找到documentation for associated storage here。您应该知道使用关联对象会降低性能(速度和内存)。它们是一个巧妙的技巧,但您可能想问自己是否有更好的方法来做您想做的任何事情。 (如果您问我,技巧中最巧妙的部分是运行时将根据您指定的策略为您处理-dealloc 上的-releases;有关更多信息,请参阅文档。)
现在是宏:
#ifndef ASSOCIATED_STORAGE_PROPERTY_IMP
#define THREE_WAY_PASTER_INNER(a, b, c) a ## b ## c
#define THREE_WAY_PASTER(x,y,z) THREE_WAY_PASTER_INNER(x,y,z)
#define ASSOCIATED_STORAGE_PROPERTY_IMP(type, setter, getter, policy) \
static void * const THREE_WAY_PASTER(__ASSOCIATED_STORAGE_KEY_, getter, __LINE__) = (void*)&THREE_WAY_PASTER(__ASSOCIATED_STORAGE_KEY_, getter,__LINE__); \
\
- (type)getter { return objc_getAssociatedObject(self, THREE_WAY_PASTER(__ASSOCIATED_STORAGE_KEY_, getter,__LINE__) ); } \
\
- (void)setter: (type)value { objc_setAssociatedObject(self, THREE_WAY_PASTER(__ASSOCIATED_STORAGE_KEY_, getter,__LINE__) , value, policy); } \
#endif
如果你在你的头文件中弹出它,那么上面的例子可以简化为:
#import <objc/runtime.h>
@interface UIViewController (SOAdditions)
@property (atomic, readwrite, copy) NSString* myProperty;
@end
@implementation UIViewController (SOAdditions)
ASSOCIATED_STORAGE_PROPERTY_IMP(NSString*, setMyProperty, myProperty, OBJC_ASSOCIATION_COPY)
@end
不用说,您在 @property 声明中声明的策略(即保留/复制/分配、原子/非原子)需要与您在使用宏(和/或调用底层 API)时使用的策略相匹配,如果你不使用宏),否则你最终会泄漏内存(或崩溃)。
另外,为了强调,我再说一遍。这个技巧不是“免费的”,所以请务必衡量性能并确保使用它所获得的任何好处都是值得的。
编辑:我将回溯一点关于关联对象存储的性能损失的强调和可怕的警告。有惩罚,但快速调查告诉我,以这种方式实现的属性并不比它们的 @synthesized 和 ivar 支持的等价物差多少。测试有点做作,但是有 10,000,000 个对象,每个对象都有 5 个关联存储支持的 iVar,我看到性能设置和获取速度降低了约 30%。恕我直言,这真的不是那么可怕。我期待更糟。与集合操作相关的内存管理(保留、复制)所花费的时间使关联查找的开销相形见绌。