在上一篇文章中,我们主要谈了这两件事情:
如何使用 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 控制台输出的调试信息猜测的:
objc[1155]: Class DJIVideoPreviewer is implemented in both
/private/var/containers/Bundle/Application/4BA27205-28B7-4EDE-9A31-0FAC7635165D/Mesh.app/Frameworks/DJIWidget.framework/DJIWidget (0x10572b750)
and
/private/var/containers/Bundle/Application/4BA27205-28B7-4EDE-9A31-0FAC7635165D/Mesh.app/Frameworks/DJIUXSDK.framework/DJIUXSDK (0x1054ec138).
One of the two will be used. Which one is undefined.
如果项目中同时引入 DJI-UXSDK
以及 DJIWidget
的话,使用我们在 DJIWidget
通过 Category
为 DJIVideoPreviewer
新增的方法会发生 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 的方式:
pod 'DJIWidget', :git => 'git@github.com:gzkiwiinc/DJIWidget.git', :tag => 'kw1.0.1'
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
的代码包含在其内部。