Khala路由组件介绍与使用

img

前言

在模组化的过程中,业务模块间的通信往往是处理最多的.与其应运而生的解决方案有以下几种:

  1. 提前注册服务
  2. Runtime 动态发现服务

前辈们在借鉴 web 服务路由设计之后,将服务绑定至固定规则的 URL 上.

  1. CTMediator: Target-Action 形式设计的路由组件.
  2. 其他以统一注册形式设计的路由.

前情提要

什么是 Target-Action?

ans: 目标-行为模式,它贯穿于iOS开发始终, 最常见的便是:

UIButton().addTarget(target: target, action: action, for: event)    

什么是 Target-Action 形式的路由?

ans: 在触发路由路径时, 通过 Runtime机制来发现具体服务,并执行.

相对于提前统一注册的路由,相当于懒加载.

Khala 路由组件使用

一. 编写 服务类(路由类)

  1. 继承自NSObject: Runtime机制本身便是基于 NSObject.
  2. 声明@objc(ClassName): 由于Xcode 8.0之后在编译时会移除未显式使用的swift类与函数,所以需要加此声明.(服务类不建议在任何模块实例化,会破坏设计逻辑)
  3. 声明@objcMembers: 在swift 4.0 中继承 NSObjectswift class 不再默认全部桥接到 objective-c,如果我们想要使用的话我们就需要在class前面加上 @objcMembers 这么一个关键字.
  4. 示例如下如下:
@objc(AModule) @objcMembers
class AModule: NSObject { }

二. 编写 服务函数(路由函数)

  1. 参数类型限制: 只能使用单个KhalaInfo(集合类型)与多个 KhalaClosure(闭包类型)

  2. 第一个参数需要匿名: 方便查找函数, 非匿名swift函数桥接至 objective-c时会形成funNameWithParam结构.(Khala前期在此花费时间较多, 最后还是采用该折中方案.)

  3. 示例如下如下:

    @objc(AModule) @objcMembers
    class AModule: NSObject,UIApplicationDelegate {
     
      func vc() -> UIViewController {
        let vc = UIViewController()
        vc.view.backgroundColor = UIColor.red
        return vc
      }
        
     func action(_ info: KhalaInfo, success: KhalaClosure, failure: KhalaClosure) {
        success(["success": #function])
        failure(["failure": #function])
      }
        
    }
    

三. 调用

  1. 通用型调用

     Khala(str: "kf://AModule/forClosures")?.call(blocks: { (item) in
       print("forClosures block3:", item)
     },{ (item) in
       print("forClosure block4:", item)
     })
    
    let value = Khala(str: "kl://AModule/doSomething")?.call()
    
  2. UIKit特例化调用:

    guard let vc = Khala(str: "kl://BModule/vc?style=0")?.viewController else { return }
    self.navigationController?.pushViewController(vc, animated: true)
    

四. URL重写 (KhalaRewrite)

该部分设计来源自nginx: 在某些场景下需要对 URL 进行转化与拦截, 例如:

  1. 服务类与服务函数存在前缀.

  2. 接收非标准 URL .

  3. URL重定向: 页面的动态升降级, 示例如下:

    let filter = KhalaRewriteFilter {
          if $0.url.host == "AModule" {
            var urlComponents = URLComponents(url: $0.url, resolvingAgainstBaseURL: true)!
            urlComponents.host = "BModule"
            $0.url = urlComponents.url!
          }
          return $0
        }
    
    Khala.rewrite.add(filter: filter)
    
    // "kl://AModule/doSomething" => "kl://BModule/doSomething"
    let value = Khala(str: "kl://AModule/doSomething")?.call()
    print(value ?? "nil")
    

五. UIApplicationDelegate 生命周期分发

部分组件往往依赖于主工程中的AppDelegate中部分函数.

  1. Khala中,需要显式的在主工程中的AppDelegate调用与处理相关逻辑.
  2. 服务类需要遵守UIApplicationDelegate协议.

主工程AppDelegate:

@UIApplicationMain
class AppDelegate: UIResponder,UIApplicationDelegate {

  var window: UIWindow?

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    let list = Khala.appDelegate.application(application, didFinishLaunchingWithOptions: launchOptions)
    return true
  }
    
}

组件中服务类:

@objc(AModule) @objcMembers
class AModule: NSObject,UIApplicationDelegate {
  
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    print("AModule.didFinishLaunchingWithOptions")
    return true
  }
  
}

六. 日志模块: KhalaHistory

每一份url请求都将记录至日志文件中, 可以在适当的时候提供开发者便利.

  1. 开启日志(默认关闭)

    Khala.isEnabledLog = true
    // or 
    Khala.history.isEnabled = true
    
  2. 文件路径: /Documents/khala/logs/

  3. 文件内容: 日期 + 时间 + URL + 参数

2018-12-01 02:06:54  kl://SwiftClass/double?  {"test":"666"}
2018-12-01 02:06:54  kl://SwiftClass/double  {"test":"666"}

七. 扩展机制: KhalaStore

khala 库中提供了一个空置的类[KhalaStore]用于盛放路由函数对应的本地函数.来简化本地调用复杂度的问题.

extension KhalaStore { 
 class func aModule_server(value: Int) -> Int {
    return Khala(str: "kf://AModule/server", params: ["value": value])!.call() as! Int
  }
}
  
@objc(AModule) @objcMembers
class AModule: NSObject {
 func server(_ info: [String: Any]) -> Int {
    return info["value"] as? Int ?? 0
  }
}

let value = KhalaStore.aModule_server(value: 46)

ps: KhalaStore 扩展文件建议统一放置.

八. 断言机制

为方便开发者使用,添加了部分场景下断言机制,示例:

khala.iOS Fatal error: [Khala] 未在[AModule]中匹配到函数[server], 请查看函数列表:
0: init
1: doSomething:
2: vc

关闭断言(默认开启):

Khala.isEnabledAssert = false

九. 缓存机制: KhalaClass.cache

  • 当路由第一次调用/注册路由类时,该路由类将被缓存至 KhalaClass.cache 中, 以提高二次查找性能.

  • 当路由类实例化时,该路由类中的函数列表将被缓存至 KhalaClass().methodLists中, 以提高查找性能.

十. 本司基于路由实现的业务架构

仅供参考, 合适才是最好的.

image

相关链接

Marmot-iOS: 基于 Khala 设计的 hybird(WKWebview <=> Native ) 通信组件.

参考

苹果核 - 解耦神器 —— 统跳协议和Rewrite引擎.

蘑菇街路由组件: MGJRouter / 阿里开源组件化方案: BeeHive

casa: iOS应用架构谈 组件化方案

bang: iOS 组件化方案探索

linhey: iOS 模组化设计方案

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,501评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,673评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,610评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,939评论 1 318
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,668评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 56,004评论 1 329
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 44,001评论 3 449
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,173评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,705评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,426评论 3 359
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,656评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,139评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,833评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,247评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,580评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,371评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,621评论 2 380