iOS Runtime特性之关联对象

作者: Tate_code | 来源:发表于2016-04-17 20:01 被阅读299次

前言

现在你准备用一个系统的类或者是你写的类,但是这个类并不能满足你的需求,你需要额外添加一个属性。
一般解决办法要么是extends(继承),要么使用category(类别)。
而我并不推荐使用extends,主要是耦合性太强,一般我使用category
我们都知道,分类中是无法设置属性的,如果在分类的声明中写@property 只能为其生成get 和 set 方法的声明,
但是有时候使用类别也需要增加一个额外属性,
那么怎么办呢?
这个时候,runtime的关联属性就能发挥它的作用了。
一般都是key value 的存在。

有关的方法

objc_setAssociatedObject 设置关联对象使用
objc_getAssociatedObject 获取关联对象使用
objc_removeAssociatedObjects 移除关联对象使用

用法

一般我用在category里,合理使用它能让category发挥更大的作用。

  • UIViewcategory

.h文件

#import <UIKit/UIKit.h>
@interface UIView (WT)
typedef void (^GestureActionBlock)(UIGestureRecognizer *ges);
/** 单点击手势 */
- (void)tapGesture:(GestureActionBlock)block;
/** 长按手势 */
- (void)longPressGestrue:(GestureActionBlock)block;
@end

.m文件

#import "UIView+WT.h"
#import <objc/runtime.h>
@implementation UIView (WT)

static char kActionHandlerTapBlockKey;
static char kActionHandlerTapGestureKey;
static char kActionHandlerLongPressBlockKey;
static char kActionHandlerLongPressGestureKey;

//单点击手势
- (void)tapGesture:(GestureActionBlock)block {
    self.userInteractionEnabled = YES;
    UITapGestureRecognizer *gesture = objc_getAssociatedObject(self, &kActionHandlerTapGestureKey);
    if (!gesture) {
        gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleActionForTapGesture:)];
        [self addGestureRecognizer:gesture];
        objc_setAssociatedObject(self, &kActionHandlerTapGestureKey, gesture, OBJC_ASSOCIATION_RETAIN);
    }
    objc_setAssociatedObject(self, &kActionHandlerTapBlockKey, block, OBJC_ASSOCIATION_COPY);
}

- (void)handleActionForTapGesture:(UITapGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateRecognized) {
        GestureActionBlock block = objc_getAssociatedObject(self, &kActionHandlerTapBlockKey);
        if (block) {
            block(gesture);
        }
    }
}

//长按手势
- (void)longPressGestrue:(GestureActionBlock)block {
    self.userInteractionEnabled = YES;
    UILongPressGestureRecognizer *gesture = objc_getAssociatedObject(self, &kActionHandlerLongPressGestureKey);
    if (!gesture) {
        gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleActionForLongPressGesture:)];
        [self addGestureRecognizer:gesture];
        objc_setAssociatedObject(self, &kActionHandlerLongPressGestureKey, gesture, OBJC_ASSOCIATION_RETAIN);
    }
    objc_setAssociatedObject(self, &kActionHandlerLongPressBlockKey, block, OBJC_ASSOCIATION_COPY);
}

- (void)handleActionForLongPressGesture:(UITapGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateBegan) {
        GestureActionBlock block = objc_getAssociatedObject(self, &kActionHandlerLongPressBlockKey);
        if (block) {
            block(gesture);
        }
    }
}

@end

我解释下里面的一些关键字段,比如OBJC_ASSOCIATION_RETAIN这个字段实际上是个枚举来的

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. 
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied. 
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.
                                            *   The association is made atomically. */
    OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.
                                            *   The association is made atomically. */
};

用法跟@property中的strong 、weak、copy 、assign 、retain等声明属性的修饰符一样,我上面用到了block就对应OBJC_ASSOCIATION_COPY,而UITapGestureRecognizerUILongPressGestureRecognizer则对应OBJC_ASSOCIATION_RETAIN进行修饰。
当然实际上我的UIViewcategory不止这些,可以参考我开发项目总结的一套库
WTSDK
可能有些地方描述得不是很好,或者描述错误了,希望你们能给我留言,thank!

相关文章

  • iOS Runtime特性之关联对象

    前言 现在你准备用一个系统的类或者是你写的类,但是这个类并不能满足你的需求,你需要额外添加一个属性。一般解决办法要...

  • iOS~runtime之关联对象

    什么是runtime? RunTime又叫运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消...

  • iOS的runtime:关联对象是如何实现的?objc_setA

    iOS的一个重要特性:runtime中一个重要功能就是关联对象。作用就是运行时动态的给对象添加变量。那么runti...

  • iOS runtime 关联对象

    最近在看runtime的相关知识,感觉里面东西还蛮多的,反正感觉runtime被戴上了很多高大上的帽子。查看了很多...

  • iOS runtime 关联对象

    关联对象 Associated Object 顾名思义,就是把一个对象关联到另外一个对象身上。 关于关联对象,ru...

  • iOS runtime之关联对象AssociatedObject

    在分类中添加属性,使用对象关联来实现: 例子:创建一个label的分类 #import@interfaceUILa...

  • iOS Runtime之四:关联对象

    一、概述 如何给NSArray添加一个属性(不能使用继承)?不能用继承,难道用分类?但是分类只能添加方法不能添加属...

  • iOS Runtime 之关联对象AssociatedObjec

    面试中总该会有人问到关于runtime的问题,虽已不是个纯native开发者,但还是有必要去整理一下以前的笔记,讲...

  • Effective Objective-C 2.0 第二章 十、

    我之前已经在这篇文章iOS runtime 关联对象做了详细介绍。本篇只是简单介绍下。 创建关联对象: id ob...

  • Associated Objects

    对象关联(或称为关联引用)本来是Objective-C 2.0运行时的一个特性; 中定...

网友评论

  • LD_左岸:如果不用runtime的关联
    自己手动实现set get 有何缺点
  • LoveY34:楼主!我想问一下你文中提到的extends和extension是同一个概念嘛?extension指的是扩展而不是继承。
  • 1c7:😁😊😉😔😖

本文标题:iOS Runtime特性之关联对象

本文链接:https://www.haomeiwen.com/subject/gxiolttx.html