上一篇文章中,我们主要谈了这两件事情:

  • 如何使用 CocoaPods 引入寄生在 Mobile-SDK-iOS 中的 DJIWidget 项目;

  • 如何利用 Runtime 的手段来 hook 住 DJIVideoPreviewer 的关键函数从而获取解码后的 pixelBuffer;

而后来发生了两件事情,促使这篇文章诞生:DJIWidget 项目被抽出独立管理

1. DJIWidget 项目被抽出独立管理

DJISDK 团队将 DJIWidget 抽出来独立管理,并为添加了 CocoaPods 支持,这一举措非常值得肯定。但是,现在只能以 static lib 的方式引入,也就是说项目 podfile 里面的 use_frameworks! 要去掉。

2. DJI-UXSDK 中包含了 DJIWidget

这点是在根据 Xcode 控制台输出的调试信息猜测的:

  1. objc[1155]: Class DJIVideoPreviewer is implemented in both
  2. /private/var/containers/Bundle/Application/4BA27205-28B7-4EDE-9A31-0FAC7635165D/Mesh.app/Frameworks/DJIWidget.framework/DJIWidget (0x10572b750)
  3. and
  4. /private/var/containers/Bundle/Application/4BA27205-28B7-4EDE-9A31-0FAC7635165D/Mesh.app/Frameworks/DJIUXSDK.framework/DJIUXSDK (0x1054ec138).
  5. One of the two will be used. Which one is undefined.

如果项目中同时引入 DJI-UXSDK 以及 DJIWidget 的话,使用我们在 DJIWidget 通过 CategoryDJIVideoPreviewer 新增的方法会发生 Unrecognized Selector 的问题而导致闪退。问题的原因应该与 DJI-UXSDK 中包含了 DJIWidget 的代码有关系,但还没清楚弄透,敬请等待后面更新。

3. 再度高效并充分使用 DJIWidget

有鉴于上面两点,我们再度开始「对 DJIWidget 的高效并充分利用」的探索。

3.1 Podfile 中的 DJIWidget 指定方式

由于原仓库中 Podspec 的编写有限制,不能以 use_frameworkds! 的方式引入,所以我们自己重新写了一份 Podspec。其内容大体上还是参照上一篇文章中阐述的编写方式,只不过对一些路径的指定进行了更新,以适应 DJIWidget 的项目结构,具体内容可以在 Kiwi Repo 下看到。

另外还是由于 pod lib lint 时的编译问题,没能顺利将这份 Podspec 推到私有 spec repo,这里暂未投入时间研究,因此项目中对 DJIWidget 的引入方式仍然需要采用 git + tag 的方式:

  1. pod 'DJIWidget', :git => 'git@github.com:gzkiwiinc/DJIWidget.git', :tag => 'kw1.0.1'
  2. pod 'DJIWidget/DJIVideoPreviewerExtension', :git => 'git@github.com:gzkiwiinc/DJIWidget.git', :tag => 'kw1.0.1'

同样,为了避免后面维护的时候,拉取原仓库的代码时可能发生的 tag 冲突,也为了清晰起见,所有由 kiwi 打的 tag 前面都加上 kw 前缀。

3.2 取回解码后的图像 buffer

由于上面提到的 DJI-UXSDK 内包含 DJIWdiget 的问题,这里转而使用子类化的方式来回避这个问题:

  • 声明 KWVideoPreviewer 并继承 DJIVideoPreviewer

  • KWVideoPreviewer 内部增加 delegate 属性;

  • 重写 videoProcessFrame 方法,加入 buffer 的转换以及调用 delegate 的逻辑;

  • 外部项目使用 DJIVideoPreviewer 的地方全都改为使用 KWVideoPreviewer

KWVideoPreviewer 的全部代码可以在 Kiwi Repo 中的 DJIVideoPreviewerExtension 文件夹里面看到。

当然这里的 best practice 可能是 DJI-UXSDK 的 podspec 中声明对 DJIWidget 的依赖,而不是直接将 DJIWidget 的代码包含在其内部。