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 扩展一个方法。
NSArray+Random.h
#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.m
#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 编程的灵活性,但也不能滥用,会导致程序不好理解。
相关推荐
源码zanqunet 2020-10-28
theowl 2020-08-18
qiximiao 2020-08-03
风萧萧梦潇 2020-07-28
Andrewjdw 2020-07-26
huakai 2020-07-26
XCMercy 2020-07-19
georgeandgeorge 2020-07-19
Jonderwu 2020-07-19
源码物语 2020-07-18
XGQ 2020-06-21
aNian 2020-06-16
郴州小程序 2020-06-13
园搬家测试账号 2020-06-12
Wonder的学习 2020-06-08
小方哥哥 2020-06-07
LULUBAO 2020-06-05
学习备忘录 2020-06-03
RocNg 2020-06-01