热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

runtime关联属性示例

前言在开发中经常需要给已有的类添加方法和属性,但是Objective-C是不允许给已有类通过分类添加属性的,因为类分类是不会自动生成成员变量的。但是,我们可以通过运行时机制就可以做到了。本篇文章适合新

前言

在开发中经常需要给已有的类添加方法和属性,但是Objective-C是不允许给已有类通过分类添加属性的,因为类分类是不会自动生成成员变量的。但是,我们可以通过运行时机制就可以做到了。

本篇文章适合新手阅读,手把手教你如何在项目中使用关联属性!

API介绍

我们先看看Runtime提供的关联API,只有这三个API,使用也是非常简单的:

 
123456789101112131415161718192021222324252627282930313233343536373839404142  /** * Sets an associated value for a given object using a given key and association policy. * * @param object The source object for the association. * @param key The key for the association. * @param value The value to associate with the key key for object. Pass nil to clear an existing association. * @param policy The policy for the association. For possible values, see “Associative Object Behaviors.” * * @see objc_setAssociatedObject * @see objc_removeAssociatedObjects */void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) /** * Returns the value associated with a given object for a given key. * * @param object The source object for the association. * @param key The key for the association. * * @return The value associated with the key \e key for \e object. * * @see objc_setAssociatedObject */id objc_getAssociatedObject(id object, const void *key) /** * Removes all associations for a given object. * * @param object An object that maintains associated objects. * * @note The main purpose of this function is to make it easy to return an object *  to a "pristine state”. You should not use this function for general removal of *  associations from objects, since it also removes associations that other clients *  may have added to the object. Typically you should use \c objc_setAssociatedObject *  with a nil value to clear an association. * * @see objc_setAssociatedObject * @see objc_getAssociatedObject */void objc_removeAssociatedObjects(id object) 

实际上,我们几乎不会使用到objc_removeAssociatedObjects函数,这个函数的功能是移除指定的对象上所有的关联。既然我们要添加关联属性,几乎不会存在需要手动取消关联的场合。

设置关联值(Setter)

对于设置关联,我们需要使用下面的API关联起来:

 
123  void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) 

参数说明:

  • object:与谁关联,通常是传self
  • key:唯一键,在获取值时通过该键获取,通常是使用static const void *来声明
  • value:关联所设置的值
  • policy:内存管理策略,比如使用copy

获取关联值(Getter)

如果我们要获取所关联的值,需要通过key来获取,调用如下函数:

 
123  id objc_getAssociatedObject(id object, const void *key) 

参数说明:

  • object:与谁关联,通常是传self,在设置关联时所指定的与哪个对象关联的那个对象
  • key:唯一键,在设置关联时所指定的键

关联策略

我们先看看设置关联时所指定的policy,它是一个枚举类型,看官方说明:

 
1234567891011121314151617  /** * Policies related to associative references. * These are options to objc_setAssociatedObject() */typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {    OBJC_ASSOCIATION_ASSIGN = 0,           /**    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**                                            *   The association is not made atomically. */    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**                                            *   The association is not made atomically. */    OBJC_ASSOCIATION_RETAIN = 01401,       /**                                            *   The association is made atomically. */    OBJC_ASSOCIATION_COPY = 01403          /**                                            *   The association is made atomically. */}; 

我们说明一下各个值的作用:

  • OBJC_ASSOCIATION_ASSIGN:表示弱引用关联,通常是基本数据类型,如intfloat,非线程安全
  • OBJC_ASSOCIATION_RETAIN_NONATOMIC:表示强(strong)引用关联对象,非线程安全
  • OBJC_ASSOCIATION_COPY_NONATOMIC:表示关联对象copy,非线程安全
  • OBJC_ASSOCIATION_RETAIN:表示强(strong)引用关联对象,是线程安全的
  • OBJC_ASSOCIATION_COPY:表示关联对象copy,是线程安全的

扩展属性

我们来写一个例子,扩展UIControl添加Block版本的TouchUpInside事件。

扩展头文件声明:

1234567891011  #import  typedef void (^HYBTouchUpBlock)(id sender); @interface UIControl (HYBBlock) @property (nonatomic, copy) HYBTouchUpBlock hyb_touchUpBlock; @end 

扩展实现文件:

123456789101112131415161718192021222324252627282930313233343536373839  #import "UIControl+HYBBlock.h"#import  static const void *sHYBUIControlTouchUpEventBlockKey = "sHYBUIControlTouchUpEventBlockKey"; @implementation UIControl (HYBBlock) - (void)setHyb_touchUpBlock:(HYBTouchUpBlock)hyb_touchUpBlock {  objc_setAssociatedObject(self,                           sHYBUIControlTouchUpEventBlockKey,                           hyb_touchUpBlock,                           OBJC_ASSOCIATION_COPY);    [self removeTarget:self              action:@selector(hybOnTouchUp:)    forControlEvents:UIControlEventTouchUpInside];    if (hyb_touchUpBlock) {    [self addTarget:self             action:@selector(hybOnTouchUp:)   forControlEvents:UIControlEventTouchUpInside];  }} - (HYBTouchUpBlock)hyb_touchUpBlock {  return objc_getAssociatedObject(self, sHYBUIControlTouchUpEventBlockKey);} - (void)hybOnTouchUp:(UIButton *)sender {  HYBTouchUpBlock touchUp = self.hyb_touchUpBlock;    if (touchUp) {    touchUp(sender);  }} @end 

推荐阅读
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了在Java中gt、gtgt、gtgtgt和lt之间的区别。通过解释符号的含义和使用例子,帮助读者理解这些符号在二进制表示和移位操作中的作用。同时,文章还提到了负数的补码表示和移位操作的限制。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
author-avatar
erryeg_342
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有