Swift组件化路由--SwiftMediator

Posted Swift开源变现之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift组件化路由--SwiftMediator相关的知识,希望对你有一定的参考价值。

在OC上搞得风生水起的组件化必不可少的就是路由,用于解耦、调度整个APP内组件之间的跳转、传参等等。有依赖协议注册的方案也有target-action。在Swift语言下唯一不同的就是Runtime受到了制约,但是协议却更加好用,所以路由的实现方案更加精简灵活多样,我这提供一个简便的路由实现方案,不需要注册表,不需要大面积改动代码,可以让模块间无耦合的调用服务、页面跳转。无需注册,不需要协议,只需要知道目标VC的类名和module名称。

实现原理:

  1. 生成对象

  2. 属性赋值

  3. 获取最上层VC

  4. 执行跳转或执行方法

其中 生成对象 这地方主要是针对性的初始化VC或者class,根据命名空间+Class名称反射出来这个类然后初始化。然后属性赋值,这个复制过程OC有Runtime执行,Swift这款单独提供了一个Mirror,可以根据对象反射出来这个对象的属性列表,按照惯例反射两层就行了。我的方案是根据传参判断属性是否存在再考虑复制

 /// 判断属性是否存在 /// - Parameters: /// - name: 属性名称 /// - obj: 目标对象 private func getTypeOfProperty (_ name: String, obj:AnyObject) -> Bool{ // 注意:obj是实例(对象),如果是类,则无法获取其属性 let morror = Mirror.init(reflecting: obj) let superMorror = Mirror.init(reflecting: obj).superclassMirror  for (key,_) in morror.children { if key == name { return true } }  guard let superM = superMorror else { return false }  for (key,_) in superM.children { if key == name { return true } } return false }  /// KVC给属性赋值 /// - Parameters: /// - obj: 目标对象 /// - paramsDic: 参数字典Key必须对应属性名 private func setObjectParams(obj: AnyObject, paramsDic:[String:Any]?) { if let paramsDic = paramsDic { for (key,value) in paramsDic { if getTypeOfProperty(key, obj: obj){ obj.setValue(value, forKey: key) } } } }


剩下的查找最上层VC就是递归window的rootVC,然后根据最上层的VC去执行Push或者Present操作,跳转到指定的VC


在某些特定情况下也需要有执行函数的操作,也是根据字符串反射Selector,然后再执行相应的类或者对象的Selector即可,OC上有NSInvocation可以执行命令调用方法并且拿到回调,但是在Swift上还是perform更加灵活一些,我这的封装只做了两个参数的传递,实际上perform可以做到更多。

 /// 路由调用实例对象方法:必须标记@objc 例子:@objc class func qqqqq(_ name: String) /// - Parameters: /// - objc: 初始化好的对象 /// - selName: 方法名 /// - param: 参数1 /// - otherParam: 参数2 @discardableResult public func callObjcMethod(objc: AnyObject, selName: String, param: Any? = nil, otherParam: Any? = nil ) -> Unmanaged<AnyObject>?{  let sel = NSSelectorFromString(selName) guard let _ = class_getInstanceMethod(type(of: objc), sel) else { return nil } return objc.perform(sel, with: param, with: otherParam) }  /// 路由调用类方法:必须标记@objc 例子:@objc func qqqqq(_ name: String) /// - Parameters: /// - moduleName: 组件名称 /// - className: 类名称 /// - selName: 方法名 /// - param: 参数1 /// - otherParam: 参数2 @discardableResult public func callClassMethod(className: String, selName: String, moduleName: String? = nil, param: Any? = nil, otherParam: Any? = nil ) -> Unmanaged<AnyObject>?{  var namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String if let name = moduleName { namespace = name } let className = "\(namespace).\(className)" guard let cls: AnyObject? = NSClassFromString(className) else { return nil }  let sel = NSSelectorFromString(selName) guard let _ = class_getClassMethod(cls as? AnyClass, sel) else { return nil }  return cls?.perform(sel, with: param, with: otherParam) }

剩下的工作就是对openURL进行处理了根据URL携带过来的数据进行VC初始化、赋值、跳转等操作。


APP生命周期抓取

一些组件可能需要对AppDelegate生命周期比较在意需要做一些初始化操作。这里也做了一些生命周期抓取的工作,多个组件勾取生命周期在数组里添加即可


下面就可以愉快的在swift下边使用组件化带来的便利了。


OC组件化路由:https://github.com/jackiehu/JHMediator

Swift组件化路由:https://github.com/jackiehu/SwiftMediator

以上是关于Swift组件化路由--SwiftMediator的主要内容,如果未能解决你的问题,请参考以下文章

具有完美身份验证和路由的服务器端 Swift

通过 TOR swift 路由 WKWebView

迁移 Swift 和更新 Alamofire 后,我的路由器无法工作

声明枚举路由器 Alamofire swift 3.0

如何从 AppDelegate.swift 路由到任何视图控制器

如何在 Swift iOS 中获取路由器的 IP 地址