zoukankan      html  css  js  c++  java
  • Swift 路由机制设计

    设计模式

    APP设计模式多种多样,从最初的MVC到MVVM,再到MVP,VIPER等。越来越多的设计模式被开发出来并得以应用,但不论我们用到哪种设计模式,只需要记住高内聚、低耦合那边是好的设计模式。在这里笔者整理了一份demo以帮助大家更好的理解Swift版路由机制的设计

    APP路由机制出现

    笔者了解到最开始分享路由机制的文章是由蘑菇街团队提供链接,其利用url注册来进行界面推出和传值。随后某位大神吐槽其机制有问题链接。在这里笔者也开始思考过这个问题,并从他们的思路中得出了适合自己的路由机制设计。路由机制原理、优点等信息网上有太多的资料可供参考,笔者不在这里赘述。下面就为大家介绍笔者的路由机制设计方式

    路由机制设计原理

    笔者觉得路由机制的设计主要涉及到两点问题

    • 推出界面(确定的目标控制器)
    • 数据传输(正向传值和反向传值)

    推出界面

    界面推出笔者选择了最为简单直接的一种方式,直接通过类名确定需要推出的控制器界面。再由当前控制器选择进行何种方式的界面推出。在OC中可以直接通过类名转化为class并生成控制器,但在Swift中由于多了命名空间的原因需要由空间名+类名的方式来生成。具体代码如下:

    //这里的BQRouterCommProtocol是为数据传输准备的协议,会在数据传输部分进行说明
    static func loadVc<T: BaseVc>(vcName:String, spaceName: String? = nil) -> T where T:BQRouterCommProtocol {
            var clsName = ""
            if let space = spaceName{
                clsName = space + "." + vcName
            }else {
                let spaceName = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String
                clsName = spaceName! + "." + vcName
            }
            let cls = NSClassFromString(clsName) as? BaseVc.Type
            let vc = cls?.init()
            if let valueVc = vc {
                return valueVc as! T
            }else {
                //当无法生成对应的控制器时,返回一个默认的错误控制器用以说明
                return ErrorVc() as! T
            }
        }
    

    数据传输

    当要推出的控制器视图有了之后,便要考虑数据传输问题,首先是正向传值,这种比较简单直接略过,我们需要主要思考的是反向传值方式,为了做到解耦,笔者最开始思考的方式是直接使用NotificationCenter。考虑到其使用时效率问题(其本质原理是通过KVO方式去进行操作),因此笔者模拟通知中心设计了一个路由通信管理器。

    通信管理器设计思路
    1. 通信管理器注册进行通信的控制器
    2. 通信管理器传输数据到可接受的控制器
    3. 当控制器释放时,从通信管理器中反注册

    先设计通信协议,目的是保证数据传输方式的统一和规范

    protocol BQRouterCommProtocol:NSObjectProtocol {
        var removeIndex: Int { get set } //用于反注册使用,初始数值小于0
        func loadVcInfo(params:Any) //用于正向传值
        func reciveRouterComm(name:Notification.Name, params:Any?) //用于反向传值
    }
    

    为了保证注册后控制器不被通信管理器强引用,中间使用代理类进行桥接,以便控制器可以正常析构,在反注册后就移除中间代理类

    class BaseVcProxy: NSObject {
        weak var vc:BQRouterCommProtocol?
        var notifiArr:[Notification.Name] = []
        init(vc: BQRouterCommProtocol) {
            self.vc = vc
            super.init()
        }
    }
    

    最后进行通信管理

    这里模仿通知中心的方式来进行通信管理
    //注册(重复注册无效)
    class public func addRouterComm(names:Notification.Name..., target: BQRouterCommProtocol) 
    //发送数据
    class public func postRouterComm(name:Notification.Name, params:Any? = nil)
    //反注册
    class public func romveRouterComm(target: BQRouterCommProtocol)
    

    通信管理器关键代码如下:

    private func addComm(names:[Notification.Name], target: BQRouterCommProtocol) {
        for weakVc in self.commObjcs {
            if let vc = weakVc.vc {
                if (vc as! UIViewController) == (target as! UIViewController){
                    return
                }
            }
        }
        let weakVc = BaseVcProxy(vc: target)
        weakVc.notifiArr.append(contentsOf: names)
        self.commObjcs.append(weakVc)
        target.removeIndex = self.commObjcs.index(of: weakVc)!
    }
    private func postComm(name:Notification.Name, params:Any?) {
        for weakVc in self.commObjcs {
            if let vc = weakVc.vc {
                if weakVc.notifiArr.contains(name) {
                    vc.reciveRouterComm(name: name, params: params)
                }
            }
        }
    }
    private func removeComm(target: BQRouterCommProtocol) {
        if target.removeIndex >= 0 {
            self.commObjcs.remove(at: target.removeIndex)
        }
    }
    

    到这里大家应该都看出笔者路由设计的概貌了,如还是不太清楚,建议对照demo进行梳理

    后记

    此路由机制的设计相对来说比较简单,却也是路由机制的主干部分。如果想要丰富细化,仍有很多细节可处理。这个就看大家项目的实际需求了。在笔者看来路由机制其实可以作为一种架构设计来说,具体到控制其中又可以分为各种设计模式了。希望这篇文章能让大家了解到Swift路由设计的方式。如有任何错误之处欢迎指正!

  • 相关阅读:
    解决PyQt5在安装后无法找到Designer.exe问题,两个位置可供参考
    观察者模式
    策略模式
    模板方法模式(下)
    学过的技术容易忘,怎么办?
    Mysql主从配置
    Springboot处理CORS跨域请求
    SpringBoot学习2之注解简单配置Springboot+MyBatis
    Confluence7.4安装并破解汉化教程
    mysql json类型
  • 原文地址:https://www.cnblogs.com/purple-sweet-pottoes/p/7101087.html
Copyright © 2011-2022 走看看