关于Swift5.0开发SDK合并库遇到的不适配问题及解决方案

简书原创处女作,如有不足之处希望各位谅解,本人邮箱494605779@.com,欢迎各位指正。
感谢。


进入正题,公司需求开发一款SDK,因个人对Swift语法比较熟悉,所以开发语言选择了Swift。Swift语言好处不必多言,下面就讲讲开发中遇到的一些问题。

首先是制作SDK,具体如何制作可以参考田野大佬的文章《iOS开发-使用OC/Swift开发静态库/动态库(SDK开发)》传送门 https://www.jianshu.com/p/e05363d700dd (已获得沟通授权)。里面从动态库与静态库的选择到开发打包所有步骤都非常的仔细,在这里我就不一一列举。

那么现在正文来了,我在制作SDK的过程中遇到了一个很奇怪的问题。用Xcode10.1打包然后用lipo语言合并好的合并包拖入项目中,用Xcode运行项目不管是OC的项目还是Swift项目都不会出现任何问题。但是转到Xcode10.2上面,用Xcode10.2打包合并就会出现真机或者虚拟器环境下Swift内public的方法无法找到的情况。

所以我首先用 lipo -info检查了一下,我的合并包确实是支持虚拟机和真机,那么就很奇怪了。翻阅了网上的教程都没有找到,只能从打好的包入手,看看Xcode10.1下的合并包与Xcode10.2下的合并包有何不同。

大家会发现,我们的SDK包中系统会自动生成一个xxx-Swift.h文件,问题就是出现在这里。Xcode10.1下不管是虚拟机还是真机运行xxx-Swift.h文件是这样的:

// Generated by Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"

#if !defined(__has_include)
# define __has_include(x) 0
#endif
#if !defined(__has_attribute)
# define __has_attribute(x) 0
#endif
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#if !defined(__has_warning)
# define __has_warning(x) 0
#endif

//.....中间部分不重要省略.....

#if __has_attribute(external_source_symbol)
# pragma clang attribute pop
#endif
#pragma clang diagnostic pop

而Xcode 10.2下虚拟机的xxx-Swift.h为:

#if 0
#elif defined(__x86_64__) && __x86_64__
// Generated by Apple Swift version 5.0 (swiftlang-1001.0.69.5 clang-1001.0.46.3)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"

#if !defined(__has_include)
# define __has_include(x) 0
#endif
#if !defined(__has_attribute)
# define __has_attribute(x) 0
#endif
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#if !defined(__has_warning)
# define __has_warning(x) 0
#endif

//.....中间部分不重要省略.....


#if __has_attribute(external_source_symbol)
# pragma clang attribute pop
#endif
#pragma clang diagnostic pop

#endif

真机的xxx-Swift.h为:

#if 0
#elif defined(__arm64__) && __arm64__
// Generated by Apple Swift version 5.0 (swiftlang-1001.0.69.5 clang-1001.0.46.3)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"

#if !defined(__has_include)
# define __has_include(x) 0
#endif
#if !defined(__has_attribute)
# define __has_attribute(x) 0
#endif
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#if !defined(__has_warning)
# define __has_warning(x) 0
#endif

//.....中间部分不重要省略.....

#if __has_attribute(external_source_symbol)
# pragma clang attribute pop
#endif
#pragma clang diagnostic pop

#endif

细心的读者发现了么?对的,看Xcode 10.2下的xxx-Swift.h的第一、二行。他在if后直接表明支持x86_64arm64,也就是说Xcode10.2生成的xxx-Swift.h不同环境下会直接表明是支持真机还是虚拟器。而Xcode10.1生成的xxx-Swift.h则不会区分两者。所以就导致在Xcode10.2内无法在不匹配.h的情况下找到swift的方法。

问题找到了,那么怎么解决呢?基于Xcode10.2下我们需要在lipo合并真机虚拟机库和模拟器库后加一条,合并xxx-Swift.h文件,即:

把虚拟机库下Headers文件夹中的xxx-Swift.h文件除去第一行与最后一行也就是

//这是第一行,去掉
#if 0
//这是最后一行,去掉
#endif

剩下所有代码全部复制到真机库下Headers文件夹中的xxx-Swift.h文件内第一行后:

#if 0
//添加位置
//.....省略内容.....
#endif

最后的效果是:

#if 0
#elif defined(__x86_64__) && __x86_64__
//.....省略内容.....
#pragma clang diagnostic pop

#elif defined(__arm64__) && __arm64__
//.....省略内容.....
#pragma clang diagnostic pop
#endif

现在再次试下就成功了,就是这么简单,完结撒花🎉。


下面说下两个Xcode下制作的SDK兼容问题。

经过测试,XCode10.2可以下兼容最低Swift4.0 ,但是Xcode10.2开发SDK选择Swift语言版本为5.0制作的SDK则无法再Xcode10.1上使用,因为Swift10.1仅支持到最高Swift4.2版本。所以建议各位以防万一SDK成品区分Xcode版本做两个。


最后,想想看这次ABI稳定为Swift涨了一波粉,但是我看来Swift才是刚刚开始,好语言最后终会普及,加油。

感谢各位观看,如有不解欢迎留言或者联系我。