一转培、問題:給分類(category)添加屬性
- 最近遇到一個問題:需要在一個類的Category中添加屬性先鱼;
- 可以通過 Category 給一個現(xiàn)有的類添加屬性遮晚,但是卻不能添加實例變量辆憔;
- 解決方案:通過runtime建立關(guān)聯(lián)引用;
二涤躲、解決:runtime建立關(guān)聯(lián)引用
1.引入runtime頭文件
#import <objc/runtime.h>
2.添加屬性
可以在分類(即.m文件)中添加棺耍,也可以在分類的頭文件(即.h文件)中添加。
@interface UIView (EmptyView)
@property (nonatomic, strong) UIButton *hideButton;
@end
3.實現(xiàn)getter种樱、setter
1).在implementation中添加屬性的getter和setter方法蒙袍。
//getter
- (UIButton *)hideButton {
UIButton *_hideButton = objc_getAssociatedObject(self, @selector(hideButton));
if (!_hideButton) {
_hideButton = [UIButton buttonWithType:UIButtonTypeCustom];
_hideButton.frame = CGRectMake(self.bounds.size.width/2-110, 260, 220, 44);
_hideButton.backgroundColor = [UIColor brownColor];
[_hideButton setTitle:@"Hide" forState:UIControlStateNormal];
objc_setAssociatedObject(self, @selector(hideButton), _hideButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return _hideButton;
}
//setter
- (void)setHideButton:(UIButton *)hideButton {
objc_setAssociatedObject(self, @selector(hideButton), hideButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
2).在hideButton
中使用的objc_getAssociatedOject
方法,Object-C中描述如下:
/**
* Returns the value associated with a given object for a given key.
*
* @param object The source object for the association.
* @param key The key for the association.
*
* @return The value associated with the key \e key for \e object.
*
* @see objc_setAssociatedObject
*/
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
- <a href = http://blog.leichunfeng.com/blog/2015/06/26/objective-c-associated-objects-implementation-principle/>這個函數(shù)先根據(jù)對象地址在 AssociationsHashMap 中查找其對應(yīng)的 ObjectAssociationMap 對象缸托,如果能找到則進(jìn)一步根據(jù) key 在 ObjectAssociationMap 對象中查找這個 key 所對應(yīng)的關(guān)聯(lián)結(jié)構(gòu) ObjcAssociation 左敌,如果能找到則返回 ObjcAssociation 對象的 value 值,否則返回 nil 俐镐;</a>
- 也就是在和self建立了關(guān)聯(lián)引用的所有對象中通過key找到某一個特定的對象,如果有返回該對象的value哺哼,否則佩抹,返回 nil 。
-
objc_getAssociatedObject
有兩個參數(shù)取董,第一個參數(shù)為從該object
中獲取關(guān)聯(lián)對象棍苹,第二個參數(shù)為想要獲取關(guān)聯(lián)對象的key;
對于第二個參數(shù)const void *key
,有以下四種推薦的key
值:
- 聲明
static char kAssociatedObjectKey;
茵汰,使用&kAssociatedObjectKey
作為key
值; - 聲明
static void *kAssociatedObjectKey = &kAssociatedObjectKey;
枢里,使用kAssociatedObjectKey
作為key
值; - 用
selector
蹂午,使用getter
方法的名稱作為key
值栏豺; - 而使用
_cmd
可以直接使用該@selector
的名稱,即hideButton
豆胸,并且能保證改名稱不重復(fù)奥洼。(與上一種方法相同)
3).在setHideButton
中使用的objc_setAssociatedObject
方法,Object-C中描述如下:
/**
* Sets an associated value for a given object using a given key and association policy.
*
* @param object The source object for the association.
* @param key The key for the association.
* @param value The value to associate with the key key for object. Pass nil to clear an existing association.
* @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
*
* @see objc_setAssociatedObject
* @see objc_removeAssociatedObjects
*/
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
參數(shù)說明:
-
object
和key
同于objc_getAssociatedObject
; -
value
:需要和object
建立關(guān)聯(lián)引用對象的value晚胡; -
policy
:關(guān)聯(lián)策略灵奖,等同于給property
添加關(guān)鍵字,具體說明如下表關(guān)聯(lián)策略
關(guān)聯(lián)策略
|關(guān)聯(lián)策略 |等價屬性|說明|
|------|------|------|------|
|OBJC_ASSOCIATION_ASSIGN| @property (assign) or @property (unsafe_unretained)| 弱引用關(guān)聯(lián)對象|
|OBJC_ASSOCIATION_RETAIN_NONATOMIC| @property (strong, nonatomic)| 強(qiáng)引用關(guān)聯(lián)對象估盘,且為非原子操作|
|OBJC_ASSOCIATION_COPY_NONATOMIC| @property (copy, nonatomic)| 復(fù)制關(guān)聯(lián)對象瓷患,且為非原子操作|
|OBJC_ASSOCIATION_RETAIN| @property (strong, atomic)| 強(qiáng)引用關(guān)聯(lián)對象,且為原子操作
|OBJC_ASSOCIATION_COPY| @property (copy, atomic)| 復(fù)制關(guān)聯(lián)對象遣妥,且為原子操作|
4.對添加的屬性操作
例如將添加的hideButton屬性添加到View中
- (void)showHideButton {
if (!self.hideButton.superview) {
[self addSubview:self.hideButton];
}
}
參考資料
- <a href = http://blog.leichunfeng.com/blog/2015/06/26/objective-c-associated-objects-implementation-principle>Objective-C Associated Objects 的實現(xiàn)原理</a>;
- <a href = http://www.reibang.com/p/3cbab68fb856>給分類(Category)添加屬性</a>;
- <a href = http://www.reibang.com/p/535d1574cb86>iOS Category中添加屬性和成員變量的區(qū)別</a>擅编。
Github鏈接
<a href = https://github.com/JixinZhang/CategoryDemo/tree/master>查看代碼請點擊這里</a>