使用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。您應該意識到使用關聯對象時會出現性能(速度和內存)損失。他們是一個巧妙的技巧,但你可能想問問自己,是否有更好的方法去做你想做的事情。 (如果你問我,這個技巧的最小部分是,運行時會根據你指定的策略爲你處理-releases
,-dealloc
;查看文檔以獲得更多信息。)
現在這裏是宏:
#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
應該不用說,該政策(即挽留/複製/分配,原子/ nonatomic)你在@property dec中聲明laration需要符合您在使用宏時使用的策略(和/或調用底層API,如果您不使用宏),否則您最終會泄漏內存(或崩潰)。
此外,我再說一遍重點。這個技巧不是「免費」的,所以請務必衡量性能,並確保使用此功能獲得的任何好處都是值得的。
編輯:我將回溯一下我關於關聯對象存儲性能處罰的強調和可怕警告。這是一種懲罰,但是一項快速調查告訴我,以這種方式實施的財產並不比它們的合成和ivar支持的等價物差得多。這項測試有點人爲設計,但是擁有10,000,000個對象,每個對象都有5個關聯存儲支持的iVar,我看到性能設置和獲取速度降低了〜30%。這真的不是那麼可怕,恕我直言。我期待更糟。花費在執行與集合操作相關的內存管理(保留,複製)上的時間使聯合查找的開銷變得相當小。
爲什麼不子類化UIViewController,然後讓所有其他的子類繼承這個新類?你是如何確定ivars對所有'UIViewController'都是通用的? - 可能事實證明他們不是,並且最終使用'UIViewController'作爲存儲桶來無故無視所有包括廚房水槽在內的存儲桶。 – 2012-01-15 14:09:37
因爲我無法更改,例如'UITableViewControler'的超類。儘管我可以將每個Apples自己的UIViewController子類繼承下來,但這並不合適。我會更新我關於共同性的問題。 – 2012-01-15 14:41:27