热门标签 | 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 

推荐阅读
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社区 版权所有