swift runtime实现 事件传递工具组件的 封装

一、对于多层逆传

  1. 在开发过程中,避免不了事件、数据的逆传,因为喜欢,所以大多数逆传都至少要串4层,而这些都用block、代理传递?想像一下你要定义多少的block属性、方法,或者代理对象、协议?崩溃!
  2. 多层逆传,如果用通知,那肯定很爽,但是会浪费很多的内存空间,消耗性能。

二、组件思路

  1. 其实与其说组件不如说是一个工具,因为他确实很小。
  2. 在NSObject分类中,添加一个block属性,这个属性要用懒加载
  3. 对外暴露两个方法,一个是发送信息的方法,另外一个是接受发送的消息的方法。

三、实际代码

代码不多,但是却是省去了很多代码

1. 定义block类型

block有两个参数:
signalKey:区分事件的key
messageObj: 传递的数据

  typealias EVENTCALLBACKBLOCK = (_ signalKey: String, _ messageObj: Any)->(Any)?

2. 发送消息函数

发送消息函数参数
signalKey: 区分事件的key
message : 传递的数据
return : 返回的数据
``

 @discardableResult
    public func sendSignalFunc (signalKey SignalKey: String, message Message: Any) -> (Any)? {
        var eventBlock: EVENTCALLBACKBLOCK? = objc_getAssociatedObject(self, NSObectEventTransmitExtension.EVENTCALLBACKBLOCKKEY) as? EVENTCALLBACKBLOCK
        if (eventBlock == nil) {
            eventBlock = {(SignalKey, Message) -> (Any)? in
                print("\(self)暂时没有,注册对赢得block,请检查,你想传传递的信息为: \n\n: SignalKey: \(SignalKey)\n\n,Message: \(Message)")
            }
        }
        print("👌\(self):\(SignalKey)")
        return eventBlock!(SignalKey,Message) as (Any)?
    }

**3. 接收消息的函数

参数:
eventCallBack 这里写出你要的事件
在外层的类中调用

 func receivedSignalFunc(eventCallBack: @escaping EVENTCALLBACKBLOCK) {
        objc_setAssociatedObject(self, NSObectEventTransmitExtension.EVENTCALLBACKBLOCKKEY, eventCallBack, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }

4. 快速搭建通道

    func stitchChannelFunc(sender Sender: NSObject?) {
        if Sender == nil {
            print("🌶::sender为你nil\(self)")
            return
        }
        Sender!.receivedSignalFunc { (signalKey, message) -> (Any)? in
            return self.sendSignalFunc(signalKey: signalKey, message: message)
        }
    }

更新: 2018.4.9

解决问题: 无法推断类型。

比如我们在顶层viewController 用 receivedSignalFunc 对对应的对象的 block进行赋值。但是传递的block中的 message 的类型是翻译不出来的

  vc.receivedSignalFunc { (signalKey, message) -> (Any)? in
            if signalKey == "😁虾" {
            //message 是any类型
                if let message = message as? String {
                    print(signalKey + message)
                }
            }
            return "老胡,收到了!!!"
        }

需求是在这个地方可以推断出类型


更新:2018.5.5

类型推断代码封装:

extension NSObject {
    
 /// 类型转换 返回原始数据
    @discardableResult
    class open func py_conversionType<T>(message: Any?, success: ((_ message: T)->())?, failure:((_ objc: Any?)->())? = nil) -> Any? {
        if let message = message as? T {
            success?(message)
            return message
        }
        py_log("\n     🌶🌶🌶 类型转化出错 《\(type(of: message))》 "
            + "无法转化为"
            + " 《\(T.self)》 "
            + "类型\n"
            + "            \n🌶objc为:\n" + "\(String(describing: message))\n🌶")
        failure?(message)
        return message
    }
  1. 事件传递成功log输出:
  1. 其中key 为用于区分事件的key:String
  2. PYView -> PYViewController2 -> PYViewController 为一个事件传递的顺序
  1. 类型推断不符合log打印:
  1. 《NSString》表示objc的真实类型,《Int》为假设的类型
  2. objc 为传入的message的内容的打印



剩下的看代码吧

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

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 13,885评论 6 13
  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 14,750评论 0 15
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,737评论 19 139
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,386评论 30 472
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,791评论 25 709