Swift项目中使用Runtime

背景介绍

学习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 
#import 
@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()
    }
}

你可能感兴趣的:(Swift项目中使用Runtime)