微信号:gh_37ebe37722aa

介绍:txx的笔记分享

A Waltz with Objc Runtime II

2016-04-27 23:03 txx

前言

昨天我写了一小段代码,描述了如何实现 Category Extension。之后有很多朋友和我反馈说,核心代码懂了,但是这貌似和 Category Extension 差的有点远啊。于是我们今天就来说另外一个小技巧。

路由表的主动发现

前几天,iOS 的组件化解决方案百家争鸣。相信大家都看了滴滴、美团、蘑菇街、天猫等的技术分享。大家的解决方案大同小异,基本上都是严重依赖统跳协议。在 Github 上也可以看到很多开源的 Router 解决方案例如 HHRouter, MGJRouter 等。

只要是 Router 就肯定会引来一个问题,我在没有初始化 XXViewController 的情况下,如何让 Router 知道这个 URL 可以解析到 XXViewController 呢?

于是我们都会写这么一个东西:

[[Router sharedInstance] map: [XXViewController class] with: @"/page1/<int: post_id>"]

然后这东西一般都会写在:

+ (void) load

方法中,因为不需要我们自己手动去调用。而且保证只会执行一次。如果没见过这个方法,请自行搜索 loadinitialize 的区别。

但这有两个小缺点:

  1. Load 方法是在程序启动前进行的,如果花的时间太久会导致 iOS 触发 WatchDog 崩溃。所以苹果官方并不怎么建议在这里面实现我们的代码。

  2. Swift 中,只有 initialize 没有 load

我们就有个备选方案:开一个入口,如:[Router init],手动往里面写。

相对于 Load 来说,感觉有点蠢啊,能不能求助万能的 Runtime,让 Router 自己找到他想要注册的类?

Runtime 解题思路

  1. 获取到 iOS 上已经 Load 的全部 Class。

  2. 判断它有没有实现某个 Protocol、Selector,或者 Class 名称带有什么奇怪的后缀。

  3. 从 Protocol 中读出想要 Map 的 Path。

如果你觉得,我拿到全部的 Class 枚举一遍是一个很耗时的行为。

  1. 这确实是很耗时的,大概要耗掉几十毫秒的样子,特别是项目特别大的时候能到几百毫秒。但 Load 方法也是这么干的,所以对时间复杂度来说,只是增加了常数而已。

  2. 这个方法可以做成异步的,丢到其他的线程,最好封入一个 RACSignal,和一些网络请求串起来。全完成的时候再进入主界面,这样就完全不影响 Router 使用。

示例代码


注意,这里面拿到的有各种神奇的 Class,比如 Zombie、NSProxy 直接执行 confirm Protocol 的时候就呵呵了。建议用自己 Class 的前缀做判断,避免出问题。

在 Swift 调用 OC Runtime?

经过测试,Swift 上确确实实可以直接完成,不需要混编 OC 代码,然而性能差距还是蛮堪忧的。消耗的时间大概是 OC 的十倍以上。不知道是不是我打开姿势错了,感觉是 Swift 和 OC 来回转类型的原因导致的。

所以我推荐这块用 @objc 标记标示一下,Runtime 部分全都用 OC 来完成。

最后

这篇文章又是瞎逼逼了一大片,然后就几行代码结束战斗。我写这个系列文章的目的并不是为了讲一些 OC 黑魔法(不过下一篇真会讲比较黑的东西),而是想告诉大家 OC Runtime 可以帮助我们换一个角度考虑问题。有的时候正着做不到,或者很难实现的时候,用 Runtime 几行代码就可以搞定,这也是 AOP,Aspect Oriented Programming,即面向切面编程的精髓所在嘛。

我面试的时候经常会判敲侧击的问一些 Runtime 的问题(当然没这么裸,都是开放性问题可以通过 Runtime 来解决的),这时候面试者常常和我抬杠说学 Runtime 这玩意有啥用,写业务的时候又用不上。

每当这时我都想说,你用 OC 当吃饭的家伙,你却不知道它是怎么工作的,真的没问题么?大家一直在用的 JSPatch 不就是把 Runtime + JSB 用至登峰造极的产物么。以及,Runtime 可以拯救你的 KPI:上线前遇到灾难级别 Bug、上线后闪退崩溃率大幅上升。

这个系列的第四篇文章开始,我会介绍一些礼物说这个项目中使用 Runtime 做奇怪的事情,希望能真正地帮到大家。

 
糖炒小虾 更多文章 另辟蹊径的网络协议分析方法 逆向分析网络协议 iOS 篇 给那些刚入行的 iOS/Android 开发新手们的一些建议 [一周一算法] 基础知识 如何正确理解 Bitcode
猜您喜欢 UnitedStack发布UOS 2.0,统一架构的公有云+托管云 C 语言之父离世 4 年,Java 之父 4 年前写的纪念文章 大数据助力助力建筑“绿色化” WebAssembly Emoji 可以如何改进你的代码——严肃地讨论