博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Objective-C 中关联引用的概念
阅读量:5952 次
发布时间:2019-06-19

本文共 2803 字,大约阅读时间需要 9 分钟。

关联引用概念

利用 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 
@interface NSArray (Random)- (id)anyOne;@end

NSArray+Random.m

#import "NSArray+Random.h"#import 
@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 
#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:eitem:3,prevItem:2item:f,prevItem:earr1:3,arr2:fitem:2,prevItem:3item:d,prevItem:farr1:2,arr2:ditem:4,prevItem:2item:c,prevItem:darr1:4,arr2:citem:2,prevItem:4item:d,prevItem:carr1:2,arr2:ditem:3,prevItem:2item:f,prevItem:darr1:3,arr2:fitem:7,prevItem:3item:e,prevItem:farr1:7,arr2:eitem:1,prevItem:7item:a,prevItem:earr1:1,arr2:a

结语

综合使用关联引用和范畴,可以大大增强 OC 编程的灵活性,但也不能滥用,会导致程序不好理解。

转载地址:http://knoxx.baihongyu.com/

你可能感兴趣的文章
LLVM 4中将加入新的LLVM链接器LLD
查看>>
在HubSpot是如何应对Fat JAR困境的
查看>>
十周后,62%的PHP网站将运行在一个不受支持的PHP版本上
查看>>
当中台遇上DDD,我们该如何设计微服务?
查看>>
超级账本HyperLedger初体验
查看>>
四种方式主导你的第一个敏捷项目
查看>>
InfoQ就Spring Boot 2.0 GA版发布采访了项目牵头人Phil Webb
查看>>
Oracle开源Fn,加入Serverless之争
查看>>
美团即时物流的分布式系统架构设计
查看>>
微软发布.NET Core Tools 1.0版本
查看>>
PHP常用函数之字符串处理
查看>>
又拍云沈志华:如何打造一款安全的App
查看>>
Rust 1.27支持SIMD
查看>>
“10%时间”:优点和缺点——敏捷海滩会议上Elizabeth Pope的报告
查看>>
关于“Fluent UI”或Ribbon Design报道的补充说明
查看>>
2018年终盘点:“年度爆款”的区块链真的结束了吗?
查看>>
51信用卡 Android自动埋点实践
查看>>
敏捷现状10周年调查
查看>>
PHP Session可能会引起并发问题
查看>>
AI产品开发的核心原则:以研究为核心驱动
查看>>