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 <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()
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 14,230评论 4 61
  • 在Objective-C的项目中, 经常遇到通过runtime来获取类和对象的成员变量, 属性, 方法, 在此基础...
    icetime17阅读 10,192评论 4 18
  • 转载自:https://github.com/Tim9Liu9/TimLiu-iOS 目录 UI下拉刷新模糊效果A...
    袁俊亮技术博客阅读 14,113评论 9 105
  • 月亮爬上天空 几颗星孤零零的 栖息在水塔上的乌鸦 在空中盘旋 呼应鸣叫似是回巢的歌 路延伸一直到远方 用两脚向后推...
    营州布衣阅读 962评论 4 9
  • 亲爱的孩子们,你们在思想上的转变,对于老师而言,何尝不是一种收获。也让我觉得遇见你们是一种幸福,我将会在课堂上更加...
    旧城微笑阅读 2,241评论 3 1