runtime之objc_setAssociatedObject

在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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,624評論 30 472
  • 1.runtime體驗 1.1.引言 運行時作為面試題中高階問題必不可少的一個技能點。經(jīng)常面試官會問道是否使...
    2897275c8a00閱讀 1,078評論 0 5
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,568評論 19 139
  • 1.項目經(jīng)驗 2.基礎(chǔ)問題 3.指南認識 4.解決思路 ios開發(fā)三大塊: 1.Oc基礎(chǔ) 2.CocoaTouch...
    扶光啟玄閱讀 5,204評論 0 13
  • 吃完早飯,妻子說去趟西單商場買件衣服,好參加戰(zhàn)友聚會。想不到本來不大喜歡買衣服的她,把下個月去舟山群島的...
    楊合林閱讀 371評論 2 0

友情鏈接更多精彩內(nèi)容