本文参考自《Objective-C编程全解》【日】狄原刚志 著 唐璐 翟俊杰 译
关联引用的概念
通过分类可以为一个类追加新的方法但是不能追加实例变量。但是利用runtime,就可以为已存在的实例对象增加实例变量,这个功能叫做关联引用。将这个功能和分类组合在一起使用,即使不创建子类,也能够对类进行动态扩展。
相关语法
- 添加关联
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
//这个方法是为对象object添加以key指定的地址作为关键字,以value为值的关联引用,第一个参数指定关联引用的存储策略(类似于属性的strong,atomic,copy等等)
//通过将value指定为nil,就可以删除key的关联
- 检索关联
id objc_getAssociatedObject(id object, const void *key)
//返回object以key为关键字关联的对象,如果没有关联到任何对象,则返回nil
- 断开关联
void objc_removeAssociatedObjects(id object)
//一次性断开断开object的所有关联,不建议使用,使用objc_setAssociatedObject,传入nil作为参数来分别断开关联
- 使用
static char rkey,skey;/*静态变量,这里只利用他们的地址作为key*/
objc_setAssociatedObject(obj, &rkey, r, OBJC_ASSOCIATION_RETAIN);
objc_setAssociatedObject(obj, &skey, s, OBJC_ASSOCIATION_RETAIN);
id x = objc_getAssociatedObject(obj, &rkey);
id y = objc_getAssociatedObject(obj, &skey);
//以上的操作,相当于将x和y分别赋值了r和s。使用地址作为key的原因是为了保证唯一性,上面的rkey和skey不会被用来存储什么,也不会对其进行赋值操作。
Demo
#import <Foundation/Foundation.h>
@interface NSArray (Random)
- (id)anyOne;
@end
#import "NSArray+Random.h"
#import <objc/runtime.h>
@implementation NSArray (Random)
static char prevKey;
static int random_value(void) {//使用线性同余算法生成随机数
static unsigned long rnd = 201008;
rnd = rnd * 1103515245UL + 12345;
return (int)((rnd >> 16) & 0x7ffff);
}
- (id)anyOne {
id item;
NSUInteger count = [self count];
if (count == 0) {
return nil;
}
if (count == 1) {
return self.lastObject;
} else {
id prev = objc_getAssociatedObject(self, &prevKey);
NSUInteger index = random_value() % count;
item = [self objectAtIndex:index];
if (item == prev) {
if (++index >= count) {
index = 0;
}
item = [self objectAtIndex:index];
}
}
objc_setAssociatedObject(self, &prevKey, item, OBJC_ASSOCIATION_RETAIN);
return item;
}
#import <Foundation/Foundation.h>
#import "Person.h"
#import "NSArray+Random.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSArray *strArray = @[@"a",@"b",@"c",@"d",@"e"];
NSArray *numArray = @[@(1),@(2),@(3),@(4),@(5)];
for (int i = 0; i < 10; i++) {
NSLog(@"%@--%@",strArray.anyOne,numArray.anyOne);
}
}
return 0;
}
d--5
c--4
d--5
c--1
e--2
c--4
e--5
a--4
b--5
e--2