本文參考自《Objective-C編程全解》【日】狄原剛志 著 唐璐 翟俊杰 譯
關聯(lián)引用的概念
通過分類可以為一個類追加新的方法但是不能追加實例變量臼婆。但是利用runtime,就可以為已存在的實例對象增加實例變量儒拂,這個功能叫做關聯(lián)引用美浦。將這個功能和分類組合在一起使用署尤,即使不創(chuàng)建子類胃碾,也能夠?qū)︻愡M行動態(tài)擴展易稠。
相關語法
- 添加關聯(lián)
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
//這個方法是為對象object添加以key指定的地址作為關鍵字拿霉,以value為值的關聯(lián)引用吟秩,第一個參數(shù)指定關聯(lián)引用的存儲策略(類似于屬性的strong,atomic绽淘,copy等等)
//通過將value指定為nil涵防,就可以刪除key的關聯(lián)
- 檢索關聯(lián)
id objc_getAssociatedObject(id object, const void *key)
//返回object以key為關鍵字關聯(lián)的對象,如果沒有關聯(lián)到任何對象收恢,則返回nil
- 斷開關聯(lián)
void objc_removeAssociatedObjects(id object)
//一次性斷開斷開object的所有關聯(lián)武学,不建議使用,使用objc_setAssociatedObject伦意,傳入nil作為參數(shù)來分別斷開關聯(lián)
- 使用
static char rkey,skey;/*靜態(tài)變量火窒,這里只利用他們的地址作為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) {//使用線性同余算法生成隨機數(shù)
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