前言 现在你准备用一个系统的类或者是你写的类,但是这个类并不能满足你的需求,你需要额外添加一个属性。 一般解决办法要么是 extends(继承)
,要么使用 category(类别)
。 而我并不推荐使用 extends
,主要是耦合性太强,一般我使用 category
。 我们都知道,分类中是无法设置属性的,如果在分类的声明中写@property
只能为其生成get
和 set
方法的声明, 但是有时候使用类别也需要增加一个额外属性, 那么怎么办呢? 这个时候,runtime
的关联属性就能发挥它的作用了。 一般都是key value
的存在。
有关的方法
objc_setAssociatedObject 设置关联对象使用 objc_getAssociatedObject 获取关联对象使用 objc_removeAssociatedObjects 移除关联对象使用
用法 一般我用在 category
里,合理使用它能让category
发挥更大的作用。
.h文件
1 2 3 4 5 6 7 8 #import <UIKit/UIKit.h> @interface UIView (WT) typedef void (^GestureActionBlock)(UIGestureRecognizer *ges); /** 单点击手势 */ - (void)tapGesture:(GestureActionBlock)block; /** 长按手势 */ - (void)longPressGestrue:(GestureActionBlock)block; @end
.m文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #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 这个字段实际上是个枚举来的
1 2 3 4 5 6 7 8 9 10 11 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
,而UITapGestureRecognizer
与UILongPressGestureRecognizer
则对应OBJC_ASSOCIATION_RETAIN
进行修饰。 当然实际上我的UIView
的category
不止这些,可以参考我开发项目总结的一套库WTSDK 可能有些地方描述得不是很好,或者描述错误了,希望你们能给我留言,thank!