商业iOS端路由架构演进

背景

目前商业SDK中的点击事件,会根据不同的「事件类型」+「业务类型」,去执行不同的路由跳转逻辑,然而不同的跳转事件内部又有着很复杂的跳转逻辑,

痛点

  1. 不同的跳转逻辑之间存在耦合
    例如,在deeplink的跳转逻辑之中有其他跳转逻辑,如果dp失败后会走normal的路由跳转;或者有些业务有deeplink链接的时候跳转dpplink,没有dp的时候会跳转默认的链接。
  2. 代码可读性差,维护成本高
    在某一个click事件当中,由于产品特性,可能会包含多个跳转逻辑,例如:跳转视频、跳转网页等等。
  3. 排查问题的难度增加

基于以上现状,在排查跳转问题的时候,需要花费较长的时间去梳理代码。

现状流程图

可以从上图看出,跳转逻辑相互关联,对于代码流程处理异常艰难。

优化想法

  1. 由于每一个卡片跳转都有一定的顺序和流程。我们需要整体先后顺序。

  2. 拉产品沟通,将跳转的先后顺序以及 成功的条件进行沟通。

沟通后流程如图:

方案

初步想的方案是,根据跳转的页面的优先级,做一个类似链表的结构体,然后链表的每个子元素都是一个页面跳转流程。 根据「页面跳转的成功」条件去进行判断,如果某个子元素跳转成功,那么returen掉,如果失败,那么继续走到下一个链表的子元素。以此类推,最终走向兜底逻辑。

原理其实很简单,就是一个链式表达式,哪个成功那么就跳转哪个,后边的流程不执行。

调用方式如下:

objectivec 复制代码
//构建各个路由跳转的元素成链条     

var routers: [ChainedRouter] = [RouterA(), RouterB(), RouterC(), RouterD()...]

// 通过方法调用,并传入对应的字段

routers.chain()?.route(with: dataA, dataB: dataB, other: otherMessage)

优化架构图:

优化流程图

调用方式参考

objectivec 复制代码
//构建各个路由跳转的元素成链条     

var routers: [ChainedRouter] = [RouterA(), RouterB(), RouterC(), RouterD()...]

// 通过方法调用,并传入对应的字段

routers.chain()?.route(with: dataA, dataB: dataB, other: otherMessage)

核心代码分享

复制代码
protocol HmgRouter: AnyObject {
    // 只需看当前响应者是否响应,不需要处理责任链传递
    func tryToRoute(with model: NSObject?, context: [String: Any]?,  completionHandler: @escaping ((Bool) -> Void))
}
 
protocol HMGChainedRouter: HmgRouter, HmgRouterLifeCycle {
    var next: HMGChainedRouter? { get set }
}
 
protocol HmgRouterLifeCycle: AnyObject {
    var success: (() -> Void)? { get set }
    var failed: (() -> Void)? { get set }
    func lifeCycleCallBack(_ result: Bool)
}

extension HmgRouterLifeCycle {
    func lifeCycleCallBack(_ result: Bool) {
        if result {
            if let success = success {
                success()
            }
        } else {
            if let failed = failed {
                failed()
            }
        }
    }
}
 
extension HMGChainedRouter {
    func route(with model: NSObject?, context: [String: Any]?,  completionHandler: ((Bool) -> Void)?) {
        tryToRoute(with: model, context: context, viewAction: viewAction) { res in
            if !res, let next = self.next {
                next.route(with: model, context: context, viewAction: viewAction, completionHandler: completionHandler)
            }
            completionHandler?(res)
        }
    }
}

class HmgRouterBuilder {
 
    private var top: HMGChainedRouter?
    private var tail: HMGChainedRouter?
 
    func add(_ router: HMGChainedRouter) -> Self {
        if top == nil {
            top = router
            tail = router
        } else {
            tail?.next = router
            tail = router
        }
        return self
    }
 
    func clean() -> Self {
        top = nil
        tail = nil
        return self
    }
 
    func build() -> HMGChainedRouter? {
        return top
    }
}

extension Array where Element == HMGChainedRouter {
    func chain() -> Element? {
 
        let a: (HMGChainedRouter?, HMGChainedRouter?) = (nil, nil)
 
        return reduce(a) { (res, current) in
            let (top, tail) = res
            guard let h = top else {
                return (current, current)
            }
            tail?.next = current
            return (h, current)
        }.0
    }
}

思考

本文中的实现方式其实就是一种责任链的实现。 我的另一篇文章详细介绍了一个责任链模式的使用场景以及常规的实现方式。 责任链模式是代码中经常要用到的。责任链其实就是某个业务场景下每个处理理单元负责一部分任务,形成一个连续处理的链条,直到任务被处理或无人处理。这种模式使得代码结构清晰,易于扩展。

附上责任链文章:https://blog.csdn.net/liyunxiangrxm/article/details/130827650

相关推荐
天空属于哈夫克34 天前
企业微信二次开发:精准实现关键词自动回复
架构·企业微信
晨米酱4 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
这个DBA有点耶4 天前
MVCC深入:Read View、版本链与快照读——InnoDB并发控制的内核
数据库·mysql·架构
码流子4 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
moMo4 天前
从固定流程到问题路由:让 LangGraph RAG 按需检索
架构
白远山4 天前
上海24小时自助健身房解决方案实战指南与经验分享
java·数据库·架构·需求分析
LorryJovens4 天前
【LAAP科研】双系统具身AGI范式研究——基于LAAP认知架构与Jev概率决策模型的系统性技术调研与范式验证
人工智能·gpt·安全·架构
JQweryuiop4 天前
中小型游戏陪练工作室数字化管理实践:基于七彩屋电竞护航小程序订单、履约与绩效系统的落地复盘
大数据·游戏·小程序·架构
LONGZETECH4 天前
一线职教实测:风光 580 汽车故障诊断仿真系统,破解实车实训四大核心痛点
人工智能·学习·安全·架构·汽车
萧瑟余晖4 天前
Netty 核心组件与 Reactor 模型详解
网络·架构