组件概念问题总结

349 阅读3分钟

背景:组件大量使用module的方式引入到工程和管理组件中,其中的一些概念需要彻底搞清楚。

一、Modules的意义

1、@import是iOS7之后的新特性语法:Modules(模块导入)或者"语义引入"。Moudles可以看成是可执行framework的集合,比#import更加高效和快捷。

2、Enable Modules是默认打开的,在Target->YourApp->Build Setting->搜索Modules, 可以看到Enable Modules默认是YES,Link Frameworks Automatically也是默认打开的。这样,编译的时候自动把可能的地方换成modules的写法去编译。从而减少大量#import引入头文件的繁杂步骤。

3、@import的一个优势是开发者不需要手动将framework添加到project settings里面,它是自动完成的。使用Modules的形式,可以使用@import MapKit;还可以只加载framework里面的子submodules,比如:@import MapKit.MKAnnotation;

二、在CocoaPods中使用

1、在Podfile中 Podfile默认使用静态库use_frameworks!,添加use_frameworks!,表示Pod使用动态库,Pod/Products里都是动态库,也就是.framework文件。

2、不添加use_frameworks!,表示Pod使用静态库,Pod/Products里都是静态库,也就是.a文件。

image.png 3、在使用静态库时,有的Pod引用的库不支持module怎么处理? 可以使用use_modular_headers!替换use_frameworks!,让所有的Pod支持静态库。 也可以对某个不支持静态库的Pod后面添加:modular_headers => true来使其支持module。

pod 'SSZipArchive', :modular_headers => true

此外,使用use_modular_headers!属性时,可以使用以下方法从模块化标头中排除特定Pod:

pod 'SSZipArchive', :modular_headers => false

4、它允许你将不同的frameworks合并成一个framework,输出部分头文件。

三、Module map

Module map 指明了 framework 中的头文件逻辑结构应该如何映射为模块。 Xcode 创建 framework时自动创建的 module map 文件,会发现在 Modules 文件夹下有一个 module.modulemap 文件,内容如下:

module TYTUIKit {
  umbrella header "TYTUIKit-umbrella.h"
  export *
  module * { export * }
}

module TYTUIKit.Swift {
  header "/Users/zhanyingzhu/Library/Developer/Xcode/DerivedData/MBTytOne-fegdtrcbgueaumgplarovkssadbq/Build/Products/Debug-iphoneos/TYTUIKit/Swift Compatibility Header/TYTUIKit-Swift.h"
  requires objc
}
  • framework module XXXX 定义了一个 framework 语义的模块
  • umbrella header "XXXX.h" 说明把 XXXX.h 文件作为模块的 unbrella header,伞头文件相当于模块中所有公共头文件的一个集合,方便使用者导入。
  • export * 将所有子模块中的符号进行重导出到主模块中
  • module * { export * } 定义子模块,这里为 * 则是为 umbrella header 中的每个头文件都创建一个子模块。

理解 Clang Module 和 Module Map 语法

四、常见问题

Q:可以在runtime时加载动态库吗?

A:不可以(除非你不想上AppStore)。苹果不允许在审核后更改app的行为,类似于热修复.

Q: 可以用Swift创建静态库吗?

A:在Xcode9后,可以。CocoaPods 1.5.0也支持Swift Static Framework.

Q:我可以使用多少动态库?有限制吗?

A:我们建议将动态库控制在一定范围内。虽然有可能创建很多的动态库,但是建议尽量不要创建太多的动态库,而使用静态库。

Q: Podfile使用静态库时出现报错[!] The following Swift pods cannot yet be integrated as static libraries:,如何解决?

A:pod install 时的错误信息提示我们应该使用use_modular_headers!来让整个项目支持静态库,或者对单个Pod使用:modular_headers => true

静态库和动态库对比传送门