我们需要一些方法把自己和别人写的代码组织起来,高效地利用,并以此为基础构建软件。这就涉及到使用和维护框架。如何利用框架迅速构建应用,以及在开发和发布一个框架的时候应该注意一些什么,这是我今天想讲的主题。
我们需要一些方法把自己和别人写的代码组织起来,高效地利用,并以此为基础构建软件。这就涉及到使用和维护框架。如何利用框架迅速构建应用,以及在开发和发布一个框架的时候应该注意一些什么,这是我今天想讲的主题。
随着app的可执行二进制文件一同加载,你不能控制加载的方式和时机,所以称为静态库。
在 iOS 8 之前,iOS 只支持以静态库的方式来使用第三方的代码。
相比静态库,framework 是自包含的,你不需要关心头文件位置等,使用起来很方便。
最后编译 app 的时候.a 将被链接到最终的可执行文件中,之后每次都随着app的可执行二进制文件一同加载,你不能控制加载的方式和时机,所以称为静态库。
在 iOS 8 之前,iOS 只支持以静态库的方式来使用第三方的代码。
框架的侧重点与 app 稍有不同,像是集成上的便利程度,使用上是否方便,升级的兼容等都需要考虑
另外需要注意方法名应该是动词或者动词短语开头,而属性名应该是名词。当遇到冲突时,(比如这里的 displayName,既可以是名字也可以是动词)应该特别注意属性和方法的上下文造成的理解不同。
优先测试,测试驱动开发
Swift 中我们可以通过 module 来提供类似命名空间隔离,从而避免符号冲突。但是在对系统已有的类添加 extension 的时候还是需要特别注意命名的问题。
只 import F1 的话,编译错误没有了,但是运行的时候有可能看到虽然 import 的是 F1,但是实际上调用到的是 F2 中的方法。
这是因为虽然有命名空间隔离,但 NSObject 的 extension 实际上还是依赖于 Objective-C runtime 的,这两个框架都在 app 启动时候被加载,运行时究竟调用了哪个方法是和加载顺序相关的,并不确定。
let bundle = NSBundle(forClass: ClassInFramework.self) let path = bundle.pathForResource("resource", ofType: "png")
major 的更改表示用户必须修改自己的代码才能继续使用框架;minor 表示框架添加了新的 API,但是现有用户不需要修改代码可以保持原有行为不变;而 patch 则代表 API 没有改变,仅只是内部修正。
另一个问题是重复的依赖。Swift 运行时还没有包含在设备中,如果对于框架,将 EMBEDDED_CONTENT_CONTAINS_SWIFT 设为 YES 的话,Swift 运行库将会被复制到框架中,这不是我们想见到的。在框架开发中这个 flag 一定是 NO,我们应该在 app 的 target 中进行设置
每当 Swift 版本升级,原来 build 过的 framework 需要重新构建否则无法通过编译。对框架开发者来说,保持使用最新 release 版本的编译器来发布框架就不会有大的问题。
这是一个 none or all 的更改。