Swift组件化路由--SwiftMediator
Posted Swift开源变现之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift组件化路由--SwiftMediator相关的知识,希望对你有一定的参考价值。
在OC上搞得风生水起的组件化必不可少的就是路由,用于解耦、调度整个APP内组件之间的跳转、传参等等。有依赖协议注册的方案也有target-action。在Swift语言下唯一不同的就是Runtime受到了制约,但是协议却更加好用,所以路由的实现方案更加精简灵活多样,我这提供一个简便的路由实现方案,不需要注册表,不需要大面积改动代码,可以让模块间无耦合的调用服务、页面跳转。无需注册,不需要协议,只需要知道目标VC的类名和module名称。
实现原理:
生成对象
属性赋值
获取最上层VC
执行跳转或执行方法
其中 生成对象 这地方主要是针对性的初始化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
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
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 和更新 Alamofire 后,我的路由器无法工作