iOS 关联引用

本文参考自《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 

@interface NSArray (Random)

- (id)anyOne;

@end
#import "NSArray+Random.h"
#import 

@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 
#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

你可能感兴趣的:(iOS 关联引用)