iOS runtime实战应用:关联对象

在开始之前建议先阅读iOS runtime的基础理解篇:iOS内功篇:runtime

有筒子在面试的时候,遇到这样一个问题:“如何給NSArray添加一个属性(不能使用继承)”,筒子立马蒙逼了,不能用继承,难道用分类?但是分类貌似只能添加方法不能添加属性啊,筒子百思不得其解,直到后来接触到了runtime才恍然大悟。

什么是关联对象

关联对象是指某个OC对象通过一个唯一的key连接到一个类的实例上。
举个例子:xiaoming是Person类的一个实例,他的dog(一个OC对象)通过一根绳子(key)被他牵着散步,这可以说xiaoming和dog是关联起来的,当然xiaoming可以牵着多个dog。

怎样关联对象

runtime提供給我们的方法:

//关联对象
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
//获取关联的对象
id objc_getAssociatedObject(id object, const void *key)
//移除关联的对象
void objc_removeAssociatedObjects(id object)

变量说明:

id object:被关联的对象(如xiaoming)
const void *key:关联的key,要求唯一
id value:关联的对象(如dog)
objc_AssociationPolicy policy:内存管理的策略

objc_AssociationPolicy policy的enum值有:

OBJC_ASSOCIATION_ASSIGN = 0,          
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, 
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,  
OBJC_ASSOCIATION_RETAIN = 01401,       
OBJC_ASSOCIATION_COPY = 01403

当对象被释放时,会根据这个策略来决定是否释放关联的对象,当策略是RETAIN/COPY时,会释放(release)关联的对象,当是ASSIGN,将不会释放。
值得注意的是,我们不需要主动调用removeAssociated来接触关联的对象,如果需要解除指定的对象,可以使用setAssociatedObject置nil来实现。

关联对象的应用

1、添加公共属性

这是最常用的一个模式,通常我们会在类声明里面添加属性,但是出于某些需求(如前言描述的情况),我们需要在分类里添加一个或多个属性的话,编译器就会报错,这个问题的解决方案就是使用runtime的关联对象。
应用举例:
我们需要自定义一个tabbar,并暴露公共的属性和方法。(读者们可以思考下使用继承和分类实现的优点和不足之处)

@interface UITabBarController (Custom)@property (nonatomic, strong) SUCustomTabbar * customTabbar;@end
#import "UITabBarController+Custom.h"
#import <objc/runtime.h>@implementation UITabBarController (Custom)- (void)setCustomTabbar:(UIView *)customTabbar {//这里使用方法的指针地址作为唯一的keyobjc_setAssociatedObject(self, @selector(customTabbar), customTabbar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}- (UIView *)customTabbar {return objc_getAssociatedObject(self, @selector(customTabbar));
}//其他方法...@end

这样,我们就可以像原生的tabbar一样使用自定义的tabbar:

[self.tabBarController.customTabbar doSomgthig];

2、添加私有成员变量

有时候,需要在分类中添加不想暴露在公共声明的成员变量。
应用举例:給按钮添加点击时间的回调

@interface UIButton (Callback)- (instancetype)initWithFrame:(CGRect)frame callback:(void (^)(UIButton *))callbackBlock;@end
@interface UIButton ()@property (nonatomic, copy) void (^callbackBlock)(UIButton * button);@end@implementation UIButton (Callback)- (void (^)(UIButton *))callbackBlock {return objc_getAssociatedObject(self, @selector(callbackBlock));
}- (void)setCallbackBlock:(void (^)(UIButton *))callbackBlock {objc_setAssociatedObject(self, @selector(callbackBlock), callbackBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}- (instancetype)initWithFrame:(CGRect)frame callback:(void (^)(UIButton *))callbackBlock {if (self = [super initWithFrame:frame]) {self.callbackBlock = callbackBlock;[self addTarget:self action:@selector(didClickAction:) forControlEvents:UIControlEventTouchUpInside];}return self;
}- (void)didClickAction:(UIButton *)button {self.callbackBlock(button);
}@end

读者思考:以上代码是否会存在内存管理的问题

3、关联KVO观察者
有时候我们在分类中使用KVO,推荐使用关联的对象作为观察者,尽量避免对象观察自身。
此应用模式不再举例,有兴趣的读者可以自行深入研究,或者将代码贴到评论处。

思考

1、关联对象更多的应用模式?
2、关联对象是否是解决问题的首选?
3、关联对象的副作用?

欢迎大家交流探讨。

 

转自:http://www.jianshu.com/p/c68cc81ef763

转载于:https://www.cnblogs.com/dannygao/p/7374852.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/282682.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黑龙江科技大学计算机考研复试科目,2020年黑龙江科技大学计算机应用技术考研经验分享...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼育明考研备考策略随着IT业的迅猛发展&#xff0c;各高校计算机专业报名火爆&#xff0c;甚至文科学生跨专业报考时都会选择计算机。计算机专业竞争日趋激烈&#xff0c;那么如何在充分发挥公共科目优势的同时&#xff0c;尽量缩小专…

Mysql数据库安全性问题【防注入】

一、SQL注入实例 后台的插入语句代码&#xff1a; $unsafe_variable $_POST[user_input]; mysql_query("INSERT INTO table (column) VALUES ($unsafe_variable)"); 当POST的内容为&#xff1a; value); DROP TABLE table;--以上的整个SQL查询语句变成&#xff1…

Unexpected end of JSON input while parsing near错误解决方式(网上的方法)

原本是想创建一个create-react-app来着&#xff0c;但是在创建的中间会出现Unexpected end of JSON input while parsing near... 的错误。 在网上找到了一些方法&#xff0c;首先是清空npm的缓存。 npm cache clean --force 氮素&#xff0c;然并卵。near后面的内容变化了一下…

解决Qt5 Creator无法切换输入法(fcitx),Ubuntu中不能使用搜狗输入法录入汉字问题...

2016年6月8日修正&#xff0c;ubuntu 16.04 Qt5.7.0 以及 Qt5.6.1均测试通过在Qt5.3之前&#xff0c;我发布过解决办法 解决Qt5 Creator无法切换输入法&#xff08;fcitx&#xff09;&#xff0c;不能录入汉字问题&#xff0c;Qt5.4以及Qt5.5&#xff0c;旧办法失效&#xff0c…

目前市场上用于个人计算机的硬盘尺寸是,第5章-硬盘(计算机组装与维护).docx

ADDIN CNKISM.UserStyle一、选择题1.磁盘存储器的主要技术指标有多项&#xff0c;下面不属于硬盘指标的是( )。A.存储容量B.单碟容量C.转速D.带宽2.硬盘的平均寻道时间通常以毫秒为单位测量&#xff0c;是指( )。A.磁头从一个柱面移到另一个随机距离远的柱面所需的平均时间B.…

Xmemcached学习笔记一(安装memcached)

memcached有三种java客户端 第一种&#xff1a;Com.danga 包下面的memcached&#xff0c;需引入jar(本人用的是memcached-2.5.2.jar 文末附上附件需要的可以下载) 第二种&#xff1a;spyMemcached 第三种&#xff1a;XMemcached 据说第三种是使用最简单&#xff0c;最好用的&a…

WrapPanel 实现虚拟化

WrapPanel 实现虚拟化控件名&#xff1a;VirtualizingWrapPanel作者&#xff1a;WPFDevelopersOrg原文链接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40&#xff1b;Visual Studio 2022;项目使用 MIT 开源许可协议&#xff1b;众…

pdo连接mysql数据库(简洁明了)

一 实例化pdo对象 $dsn "mysql:dbnametest;host127.0.0.1"; $pdo new PDO($dsn,root,root);二 数据查询 1、如果不根据用户传过来的值进行操作,可以直接query sql $dsn "mysql:dbnametest;host127.0.0.1"; $pdo new PDO($dsn,root,root); $sql &qu…

一次微信小程序的快速开发体验

起因 事情是这样的 一天早上组里还早激烈的讨论某个项目的可用性和发展前景&#xff0c;突然老大说了句&#xff0c;能不能做个小程序的版本呢&#xff1f;然后大家纷纷讨论起来&#xff0c;有反对有支持&#xff0c;我就说了一句&#xff0c;刚出来的时候搞过一会。。。然后就…

造数据时踏过的坑

1.在产生随机数时,在数据规模很大的时候很难出现自己要的模型,比如某个条件的数据量,此时要写一个方法,来造一批这样的数据 2.将控制数量,文件路径写成配置文件的形式,以免重复打包 3.输入输出文件夹,可以配置以免重复打包 转载于:https://www.cnblogs.com/rocky-AGE-24/p/7376…

如何证明 ConcurrentDictionary 字典操作不全是线程安全的

前言最近&#xff0c;看到一篇文章&#xff0c;讲到《ConcurrentDictionary字典操作竟然不全是线程安全的&#xff1f;》。首先&#xff0c;这个结论是正确的&#xff0c;但文中给出的一个证明例子&#xff0c;我觉得是有问题的。相关代码如下&#xff1a;using System.Collect…

微型计算机及接口技术试题,1月自考微型计算机及其接口技术试题及答案解析...

《1月自考微型计算机及其接口技术试题及答案解析》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《1月自考微型计算机及其接口技术试题及答案解析(11页珍藏版)》请在人人文库网上搜索。1、精品自学考试资料推荐全国 2018年 1月自考微型计算机及其接口技术试题课程代码…

16-djongo中间件学习

目录 前戏 我们在前面的课程中已经学会了给视图函数加装饰器来判断是用户是否登录&#xff0c;把没有登录的用户请求跳转到登录页面。我们通过给几个特定视图函数加装饰器实现了这个需求。但是以后添加的视图函数可能也需要加上装饰器&#xff0c;这样是不是稍微有点繁琐。 学完…

PHP基础(必须熟练掌握的基础)

<?php/*** 三元运算符的应用*/ /* $a 10; $b 15; echo $a > $b ? 1 : 0; */ // 注:php7新添加的运算符比较运算符x<>y // 如果x和y相等,就返回0,如果x>y,就返回1,如果x的值小于y,就返回-1/* $a "aaa"; $b "bbb"; echo $a.$b; *//*** …

子进程无法从标准输入读取数据

每个process对象最多只能调用一次start()方法&#xff0c;join([timeout])方法会阻塞调用process对象的进程&#xff0c;直到timeout时间超时&#xff0c;或者process进程退出。如果timeout设置为None&#xff0c;则无超时时间。对于linux操作系统的进程管理&#xff0c;父进程…

Eclipse控制项目的访问名称

Eclipse控制web项目的访问名称 web项目的访问路径&#xff08;名称&#xff09;修改 1.点击项目右键-》properties找到Context root 修改成我们需要的名字即可转载于:https://www.cnblogs.com/pypua/articles/7379950.html

计算机一级选择题已做完确认,计算机一级选择题(附答案)

点击蓝字关注我们(1)按照需求功能的不同&#xff0c;信息系统已形成各种层次&#xff0c;计算机应用于管理是开始于:()A)信息处理B)人事管理C)决策支持D)事务处理正确答案&#xff1a;A解析&#xff1a;计算机用于管理&#xff0c;起源于计算机在办公应用中对大量信息、数据的处…

参加51CTO培训,PMP考试通过啦

为什么选择考PMP&#xff1f;先介绍下自己的情况&#xff0c;毕业三年&#xff0c;单位类似于平台&#xff0c;不做技术&#xff0c;常态的工作是文案、商务、市场都会涉及些&#xff0c;对未来也有些迷茫。受前辈点拨可以学一些通用的技能&#xff0c;于是我选择了PMP&#xf…

如何查看服务器并发请求连接数

https://wenku.baidu.com/view/fb553d795acfa1c7aa00cc27?pcf2#1 转载于:https://www.cnblogs.com/linewman/p/9918760.html

C# 二十年语法变迁之 C# 5 和 C# 6参考

C# 二十年语法变迁之 C# 5 和 C# 6参考https://benbowen.blog/post/two_decades_of_csharp_ii/自从 C# 于 2000 年推出以来&#xff0c;该语言的规模已经大大增加&#xff0c;我不确定任何人是否有可能在任何时候都对每一种语言特性都有深入的了解。因此&#xff0c;我想写一系…