对于 Framework 不支持@ibdesignable研究
写出这一篇文章之前,我搜索了很多的资料。牵扯出来的东西实在是太多,很多我没法理解其中的原理,可能我看的不详细,并且不需要去知道牵扯出来原理,我只是想解决办法而已。
最近写了一个控件,是为了做共享车位项目的一个选择控件。在最后的版本我加了@IBDesignable
和@IBInspectable
两个关键词用于支持 Xib
的及时预览和设置。
最近在想使用 Carthage
打包成 Framework
之后,放在 Cocoapods
进行依赖,会简单很多。
但是我们的控件在 Xib
不能及时的预览,不能及时的渲染。我们的代码可是在自己的例子里面经过测试的!
我们不但在 Swift
的例子里面测试通过,而且还在 OC
的例子里面测试通过。但是我们托管在 Cocoapods
之后,竟然无法通过了?
当时一时不明白什么原因,恰巧看到群里面有人分享说 Xcode9
之前 Swift
不支持静态库。
https://zhuanlan.zhihu.com/p/32178522?group_id=926848741735350272
当时就好奇的搜索一下什么是静态库和动态库。
https://www.jianshu.com/p/42891fb90304
下面我就说一下我的理解,简单说一下所谓的动态库是可以代码共享供其他程序使用的,比如系统的 UIKit.framework
Foundation.framework
都是存在于 iOS
系统里面。
不同的 APP
都是依赖于 iOS
系统里面这些动态库,这就所谓我们的安装包会变小。
所谓的静态库就是复制一份代码到我们的 APP
里面,比如其他第三方打包号的 Framework
,比如 Cocoapods
托管的。
说到这里,我们已经注意到为什么自己打包出来的.Framework
是赋值代码到我们 APP
是属于静态库,为什么系统的.framework
是属于共享代码属于动态库呢?
我们自己口中所谓的创建动态库和静态库究竟是怎么的一回事呢?我们看一下下面的图。
这就是我理解的图,所以对于 Framework
有三种
- 存在于
iOS
系统供其他APP
共享代码使用的真正动态库 - 存在于
APP
沙盒下面供扩展程序和主程序使用的伪动态库 - 复制代码只供主程序使用的静态库
搜索了静态库和动态库的区别之后,对比自己测试的 Demo
和自己真正用的例子发现。
自己的 Demo
都在一个工程,属于伪动态的库。但是自己打包成 Framework
不管是拖拽还是使用 Cocoapods
都已经变成了静态库了。所以应该是这个原因导致的。
后来,我就直接让代码使用 Cocoapods
进行托管。但是发现还是不行,当时就百度了
Cocoapods not support @IBDesignable
虽然这个问题在 Cocoapods
的问题列表出现很多次,但是官方给的回复是我们的库有问题和 Cocoapods
没有什么关系。
最后我再次修改了搜索的关键词
swift @IBDesignable framework not work in xib
这次搜索果然有收获,并且大概知道了解决的办法。
https://github.com/Carthage/Carthage/issues/335
http://stackoverflow.com/a/39999914/760435
一个采纳的建议为使用者自己创建子类或者分类,重写@IBDesignable
标识符。
我试了一些,是可以正常的渲染出来,但是属性还是无法在 Xib
设置。
此时此刻,我大概明白了出不来造成的原因是什么。是因为 Swift
文件会被自动 Generated Interface
头文件的时候
@IBDesignable
和@IBDesignable
关键词不会被自动转换为 OC
的宏IB_DESIGNABLE
和IBInspectable
。
因为打包成 Framework
会被自动转换为 OC
里面的头文件,因此缺少标识的宏自然无法在 Xib
进行渲染和识别。
三种方法可以解决
1.代码开源使用 Cocoapods
使用 Cocoapods
直接托管我们的源文件,这样就形成了我们所说的伪动态库。
只有在运行的时候才被编译成库,这样 Xib
就可以在编译的时候看到源文件,识别出@IBDesignable
和@IBDesignable
关键词。
2. 打包成 Framework
如果想使用 Framework
的话,比如使用 Carthage
之类。自动生成的头文件自然是无法支持的。
我们想要支持的话就必须是把我们声明@IBDesignable
和@IBDesignable
关键词的文件暴露在 public header
列表之下。
那么打包出来的 Framework
,程序也可以看到我们的源文件,自然而然的就支持 Xib 渲染了。
3. 打包成 Framework 不想让别人知道核心代码
这个就有点难度了,毕竟你不想让别人知道核心代码。又要让自己的库支持Xib
的话。
你就必须参考上面2所说的,做一个可以暴露源码的文件,把@IBDesignable
和@IBDesignable
关键词写在这个文件里面。之后再把设置的属性赋值给核心库,这样核心的类会自动生成。
类似下面
这样只不过提供库作者麻烦一些,谁让自己不愿意开源呢?
据说 Framework 不支持@IBDesignable是苹果的一个 BUG,至今还没有修复
https://openradar.appspot.com/23114017