Demo
参考自这位大神的Github,小伙伴也可以参考他的例子。
先看例子
#import <UIKit/UIKit.h>
typedef void(^GestrueBlock)(id gestrueRecognize);
@interface UIGestureRecognizer (Block)
+ (instancetype)recognizeWithAction:(GestrueBlock)gestrueBlock;
@end
#import "UIGestureRecognizer+Block.h"
#import <objc/runtime.h>
static const int targetKey;
@implementation UIGestureRecognizer (Block)
+ (instancetype)recognizeWithAction:(GestrueBlock)gestrueBlock{
__weak typeof(self) weakSelf = self;
return [[weakSelf alloc]initWithActon:gestrueBlock];
}
- (instancetype)initWithActon:(GestrueBlock)gestrueBlock{
self = [self init];
[self addActonWithBlock:gestrueBlock];
[self addTarget:self action:@selector(invoke:)];
return self;
}
- (void)addActonWithBlock:(GestrueBlock)block{
//第一步,设置关联对象
if (block) {
objc_setAssociatedObject(self, &targetKey, block, OBJC_ASSOCIATION_COPY);
}
}
- (void)invoke:(id)sender{
//取出关联对象
GestrueBlock block = objc_getAssociatedObject(self, &targetKey);
if (block) {
block(sender);
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addGestureRecognizer:[UITapGestureRecognizer recognizeWithAction:^(id gestrueRecognize) {
NSLog(@"点击了 self.view");
}]];
}
由这篇文章中可以知道,我们通过分类的方法没法直接添加属性。所以可以通过关联对象的方式间接给分类添加属性。
下面开始介绍关联对象的几个方法:
关联对象
/**
* 使用给定的键和关联策略为给定对象设置关联值。
*
* @param object 关联的源对象。
* @param key 关联的键
* @param value 关联的源对象所需要关联的值,通过nil来清除现有的关联。
* @param policy 关联策略
*
* @see objc_setAssociatedObject
* @see objc_removeAssociatedObjects
*/
void objc_setAssociatedObject(id _Nonnull object,
const void * _Nonnull key,
id _Nullable value,
objc_AssociationPolicy policy);
关联策略
/**
* Policies related to associative references.
* These are options to objc_setAssociatedObject()
*/
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. */
};
获取关联对象
/**
* 获取关联源对象下给定的 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 _Nullable objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key);
移除关联对象
/**
* 删除给定对象的所有关联。
*
* @param object 关联的源对象
*
* @note
*这个函数的主要目的是使对象返回到“原始状态”变得容易,
*你不应该使用这个函数去除对象中的关联,
*因为它还可以去除其他客户端可能添加到对象的关联。
*通常你应该使用\ c objc_setAssociatedObject和一个nil值来清除关联。
*
* @see objc_setAssociatedObject
* @see objc_getAssociatedObject
*/
void objc_removeAssociatedObjects(id _Nonnull object);