1. 程式人生 > >iOS objc_setAssociatedObject 關聯物件

iOS objc_setAssociatedObject 關聯物件

 

今天看了FDTemplateLayoutCell的原始碼,類別裡面相當頻繁使用了關聯物件,做筆記!!!學套路

主要函式:

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);

id objc_getAssociatedObject(id object, const void *key); 

void objc_removeAssociatedObjects(id object);

基本說明:關聯物件就是runTime界的NSMultableDictionary 

複製程式碼

objc_setAssociatedObject 相當於 setValue:forKey 進行關聯value物件

objc_getAssociatedObject 用來讀取物件

objc_AssociationPolicy  屬性 是設定該value在object內的屬性,即 assgin, (retain,nonatomic)...等

 objc_removeAssociatedObjects 函式來移除一個關聯物件,或者使用objc_setAssociatedObject函式將key指定的關聯物件設定為nil。

複製程式碼

相關引數

複製程式碼

key:要保證全域性唯一,key與關聯的物件是一一對應關係。必須全域性唯一。通常用@selector
(methodName)作為key。
value:要關聯的物件。 policy:關聯策略。有五種關聯策略。 OBJC_ASSOCIATION_ASSIGN 等價於 @property(assign)。 OBJC_ASSOCIATION_RETAIN_NONATOMIC等價於 @property(strong, nonatomic)。 OBJC_ASSOCIATION_COPY_NONATOMIC等價於@property(copy, nonatomic)。 OBJC_ASSOCIATION_RETAIN等價於@property(strong,atomic)。 OBJC_ASSOCIATION_COPY等價於@property(copy, atomic)。

複製程式碼

使用場景:關聯物件相當於例項變數,在類別(也有人管叫分類)裡面,不能建立例項變數, 關聯物件就可以解決這種問題。(對應屬性,有對應屬性的的runtime 解決方法,本篇文章主講 關聯物件學習)

基本使用:舉例建立 UIButton類別

複製程式碼

//
//  UIButton+Block.h
//  SectionDemo
//
//  Created by HF on 2017/7/13.
//  Copyright © 2017年 HF-Liqun. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef void (^btnBlock)(id sender);

@interface UIButton (Block)

- (void)handelWithBlock:(btnBlock)block;

@end

//
//  UIButton+Block.m
//  SectionDemo
//
//  Created by HF on 2017/7/13.
//  Copyright © 2017年 HF-Liqun. All rights reserved.
//

#import "UIButton+Block.h"
#import <objc/runtime.h>

@implementation UIButton (Block)

- (void)handelWithBlock:(btnBlock)block {

    if (block) {
        objc_setAssociatedObject(self,@selector(btnAction:) , block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    [self addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];

}

- (void)btnAction:(id)sender
{
    btnBlock block = objc_getAssociatedObject(self,@selector(btnAction:));
    if (block) {
        block(sender);
    }
}

@end

複製程式碼

注意到標記亮粉色部分 是第二個引數  const void *key 型別通常都是通常都是會採用靜態變數來作為關鍵字  可以自己建立 也可以使用"@selector(btnAction:) "。

自己設定靜態變數做關鍵字:

在FDTemplateLayoutCell 中 第二個引數進一步優化,出現了_cmd 代替了 &btnKey 或者 @selector(methodName).

因為:
_cmd在Objective-C的方法中表示當前方法的selector,正如同self表示當前方法呼叫的物件例項。

這裡強調當前,_cmd的作用域只在當前方法裡,直指當前方法名@selector。例如:

這樣處理好處是,該方法相對化簡了繁文縟節,並且可讀性良好。不容易寫錯key。

參考 FDTemplateLayoutCell中使用_cmd 的使用

至此,設定關聯物件關鍵key,一共有三種寫法:

(1)靜態變數&btnKey  

(2)@selector(methodName)

(3)_cmd