Objective-C 中關聯引用的概念

關聯引用概念

利用 OC 語言的動態性,藉助運行時(runtime)的功能,咱們能夠爲已存在的實例對象增長實例變量,這個功能叫作關聯引用。編程

添加、檢索和斷開關聯

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

該方法爲對象 object 添加以 key 指定的地址做爲關鍵字、以value爲值的關聯引用,第四個參數policy指定關聯引用的存儲策略。數組

objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key) OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);

返回 object 以 Key 爲關鍵字的關聯對象,若是沒有關聯對象,則返回 nil安全

objc_removeAssociatedObjects(id _Nonnull object)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);

斷開關聯多線程

存儲策略

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0,           /*弱引用對象保存對象*/
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /*強引用對象保存對象,非原子性*/
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /*複製一份原對象,非原子性*/
    OBJC_ASSOCIATION_RETAIN = 01401,       /*引用對象保存對象,默認原子性,多線程安全 */
    OBJC_ASSOCIATION_COPY = 01403          /*複製一份原對象,默認原子性,多線程安全*/
};

實例

假設咱們爲 NSArray 增長了一個新的隨機取元素的方法,而且取得的元素不能夠連續相同,咱們利用範疇(category)爲 NSArray 擴展一個方法。dom

NSArray+Random.hui

#import <Foundation/Foundation.h>

@interface NSArray (Random)

- (id)anyOne;

@end

NSArray+Random.m線程

#import "NSArray+Random.h"
#import <objc/runtime.h>

@implementation NSArray (Random)

static char prevKey;

- (id)anyOne {
    id item;
    NSUInteger count = [self count];
    if (count == 0) {
        return nil;
    }else if(count == 1){
        return [self lastObject];
    }else{
        id prev = objc_getAssociatedObject(self, &prevKey);//獲取關聯對象所引用的值,初次使用返回 nil
        NSUInteger index = random()%count;
        item = self[index];
        if (item == prev) {//索引相同狀況下,取下一個元素,若該索引是數組最後一個,則取第一個值
            if (++index >= count) {
                index = 0;
            }
            item = self[index];
        }
        printf("item:%s,prevItem:%s\n",[item UTF8String],[prev UTF8String]);
    }
    
    objc_setAssociatedObject(self, &prevKey, item, OBJC_ASSOCIATION_RETAIN);//存儲最後返回的對象
    return item;
}

main.mcode

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "NSArray+Random.h"

int main(int argc, char * argv[]) {
    
    
    id arr1 = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7"];
    id arr2 = @[@"a",@"b",@"c",@"d",@"e",@"f",@"g"];
    
    for (int i=0; i<15; i++) {
        printf("arr1:%s,arr2:%s\n",[[arr1 anyOne] UTF8String],
               [[arr2 anyOne] UTF8String]);
    }
    
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

運行結果

item:2,prevItem:(null)
item:e,prevItem:(null)
arr1:2,arr2:e
item:3,prevItem:2
item:f,prevItem:e
arr1:3,arr2:f
item:2,prevItem:3
item:d,prevItem:f
arr1:2,arr2:d
item:4,prevItem:2
item:c,prevItem:d
arr1:4,arr2:c
item:2,prevItem:4
item:d,prevItem:c
arr1:2,arr2:d
item:3,prevItem:2
item:f,prevItem:d
arr1:3,arr2:f
item:7,prevItem:3
item:e,prevItem:f
arr1:7,arr2:e
item:1,prevItem:7
item:a,prevItem:e
arr1:1,arr2:a

結語

綜合使用關聯引用和範疇,能夠大大加強 OC 編程的靈活性,但也不能濫用,會致使程序很差理解。對象

相關文章
相關標籤/搜索