在objectiv-c中,如果我們想在不修改源碼的基礎(chǔ)上給一個類增加方法,可以使用類別(category),但是如果想增加屬性呢?查找資料了解到,通過objective-c的運行時特性可以實現(xiàn)給類動態(tài)的添加屬性。
需要用到的兩個runtime方法:
/**
* 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.”
*/
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
/**
* 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.
*/
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
翻譯過來就是:
/**
* 將一個值(value)通過關(guān)鍵字(key)和關(guān)聯(lián)策略(policy)與給定的對象(object)關(guān)聯(lián)起來
*
* @param object 源對象
* @param key 進行關(guān)聯(lián)的關(guān)鍵字
* @param value 關(guān)聯(lián)的值
* @param policy 關(guān)聯(lián)策略
*/
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
/**
* 通過關(guān)鍵字(key)獲取到對象關(guān)聯(lián)的值(value)
*
* @param object 源對象
* @param key 進行關(guān)聯(lián)的關(guān)鍵字
*/
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
關(guān)鍵字是一個void類型的指針,每一個關(guān)聯(lián)的關(guān)鍵字必須是唯一的,通常都是會采用靜態(tài)變量來作為關(guān)鍵字。
關(guān)聯(lián)策略:這里的關(guān)聯(lián)策略和聲明屬性時使用的關(guān)鍵字類似
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
* The association is not made atomically. */
OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
* The association is made atomically. */
OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
* The association is made atomically. */
};
舉個例子
.h文件
#import <UIKit/UIKit.h>
@interface UIButton (test)
@property (nonatomic) UIColor * defaultColor;
@end
.m文件
#import "UIButton+test.h"
#import <objc/runtime.h>
static const char defaultColorKey;
@implementation UIButton (test)
@dynamic defaultColor;
- (void)setDefaultColor:(UIColor *)defaultColor {
//進行綁定,把 defaultColor 和 btn 綁定起來,將來就可以通過 btn 獲得 defaultColor 了
objc_setAssociatedObject(self, &defaultColorKey, defaultColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *)defaultColor {
//通過self 和 關(guān)鍵字 獲得綁定的 defaultColor
return objc_getAssociatedObject(self, &defaultColorKey);
}
@end
viewController
#import "ViewController.h"
#import "UIButton+test.h"
@interface ViewController ()
@property (nonatomic) UIButton * btn;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.btn];
self.btn.center = self.view.center;
}
- (UIButton *)btn {
if (_btn == nil) {
_btn = [UIButton buttonWithType:UIButtonTypeSystem];
_btn.defaultColor = [UIColor redColor];
_btn.backgroundColor = [UIColor orangeColor];
_btn.frame = CGRectMake(0, 0, 240, 60);
[_btn setTitle:@"點我試試" forState:UIControlStateNormal];
[_btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[_btn addTarget:self action:@selector(btnDidClicked:) forControlEvents:UIControlEventTouchUpInside];
}
return _btn;
}
- (void)btnDidClicked:(UIButton *)btn {
_btn.backgroundColor = btn.defaultColor;
}