当前位置: 首页 > news >正文

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 编程的灵活性,但也不能滥用,会导致程序不好理解。

相关文章:

  • 鱼骨图 - 如何绘制?
  • Centos安装gerrit
  • 模型微调
  • 专属程序员的西游记,不是程序员读不懂哦?
  • 第十八天-企业应用架构模式-基本模式
  • 人脸识别最新开发经验demo
  • 百度地图api文档实现任意两点之间的最短路线规划
  • 链表
  • Spark一些必须知道的概念
  • Linux系列(5)linux基础命令
  • 08r2活动目录迁移升级2012r2--(DHCP迁移)
  • 唯一分解定理
  • 关于 es6的 let 特性在 for 循环结构 的个人理解
  • 蚂蚁数据分析平台的演进及数据分析方法的应用
  • 从第一行代码开始开发区块链(二)
  • Apache Pulsar 2.1 重磅发布
  • crontab执行失败的多种原因
  • gops —— Go 程序诊断分析工具
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • js对象的深浅拷贝
  • ng6--错误信息小结(持续更新)
  • PAT A1050
  • Python学习笔记 字符串拼接
  • ucore操作系统实验笔记 - 重新理解中断
  • 从零开始学习部署
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 嵌入式文件系统
  • 如何编写一个可升级的智能合约
  • 使用Swoole加速Laravel(正式环境中)
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 译有关态射的一切
  • 容器镜像
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #、%和$符号在OGNL表达式中经常出现
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • (30)数组元素和与数字和的绝对差
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • .Net Core和.Net Standard直观理解
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET Micro Framework 4.2 beta 源码探析
  • .ui文件相关
  • @font-face 用字体画图标
  • @RequestBody与@ModelAttribute
  • @Transactional注解下,循环取序列的值,但得到的值都相同的问题
  • [ 隧道技术 ] cpolar 工具详解之将内网端口映射到公网
  • [20171106]配置客户端连接注意.txt
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [Angular 基础] - 数据绑定(databinding)
  • [c#基础]DataTable的Select方法
  • [c]统计数字