背景介绍
学习Swift的时候写工具类的时候突发奇想,想要使用block代替selector,尝试了很多次,最后还是无能为力,后来想到在oc中遇到过BlocksKit,遂学习参考了一下,但是用到了runtime,无法在纯Swift的项目中使用,如果使用oc与swift混编的话则可以达到效果,在此记录
OC
下面是在UIView的分类中声明的两个方法,为了给View添加一个点击事件,如同控件button一样,下面两个方法的效果一样
@interface UIView (Helper)
-(void)addTapAction:(SEL)action forTarget:(id) aTarget;
-(id)addTapActionBlock:(void (^)(id sender))action;
@end
下面是对两个方法的实现,第一个方法直接将sel传递,第二个方法是通过运行时的两个方法相当于先将block通过key保存起来然后再拿出来调用block(暂时先这么理解,因为我觉得不是那么简单,后面会更改见解)
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
#import "UIView+Helper.h"
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>
@implementation UIView (Helper)
-(void)addTapAction:(SEL)action forTarget:(id) aTarget
{
self.userInteractionEnabled=YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:aTarget action:action];
[self addGestureRecognizer:tap];
}
- (id)addTapActionBlock:(void (^)(id sender))action{
self.userInteractionEnabled=YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(testHandle:)];
[self addGestureRecognizer:tap];
if (!self) return nil;
objc_setAssociatedObject(self, @"qeqweqeqweqeweretertet", action, OBJC_ASSOCIATION_COPY_NONATOMIC);
return self;
}
- (void)testHandle:(id)sender{
void (^block)(id) = objc_getAssociatedObject(self, @"qeqweqeqweqeweretertet");
if (block) block(self);
}
@end
Swift
在swift中实现上面的block方式添加点击事件
首先看下面两行oc的代码,注意key为“ UnsafeRawPointer”格式,不可以直接用String字符串,我之前用的字符串一直报nil错
public func objc_setAssociatedObject(_ object: Any!, _ key: UnsafeRawPointer!, _ value: Any!, _ policy: objc_AssociationPolicy)
public func objc_getAssociatedObject(_ object: Any!, _ key: UnsafeRawPointer!) -> Any!
然后在UIView的扩展文件中写下面代码
import Foundation//
struct RuntimeKey {//声名runtime的key值
static let viewTapKey = UnsafeRawPointer.init(bitPattern: "ViewTapKey".hashValue)
}
extension UIView{
func addTapActionBlock(action : UIViewCategoryActionBlock?) {
self.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target:self, action:#selector(UIView.testHandle))
self.addGestureRecognizer(tap)
objc_setAssociatedObject(self, RuntimeKey.viewTapKey, action, .OBJC_ASSOCIATION_COPY_NONATOMIC)//此处相当于保存block
}
func testHandle() {
let block = objc_getAssociatedObject(self, RuntimeKey.viewTapKey) as! UIViewCategoryActionBlock//此处相当于提取block
block()
}
}
网友评论