我有一个现有的 iOS 应用程序,并且想要添加我一直在开发的大量代码作为另一个项目,只是为了便于测试。新块基本上处理将图像保存到各种共享服务等。因为共享代码需要大量测试和未来更新,我想知道将代码块合并到我现有应用程序中的最佳方法是什么。
我不知道它应该是静态库、动态库还是框架,老实说,我不确定有什么区别,或者我应该如何去做并在 Xcode 中进行设置。
我所知道的是,我需要/想要为共享代码保留一个单独的测试和更新应用程序,并让主应用程序使用它。
首先,一些通用定义(特定于 iOS):
静态库 - 在编译时链接的代码单元,不会改变。
但是,iOS 静态库不允许包含图像/资产(仅限代码)。不过,您可以通过使用媒体包来解决这一挑战。
可以在 Wikipedia here 上找到更好、更正式的定义。
动态库 - 在运行时链接的代码和/或资产单元,可能会发生变化。
但是,只允许 Apple 为 iOS 创建动态库。你不能创建这些,因为这会让你的应用被拒绝。 (有关确认和推理,请参阅 this 其他 SO 帖子)。
软件框架 - 一组完成任务的编译代码......因此,您实际上可以拥有静态框架或动态框架,它们通常只是上述的编译版本。
有关详细信息,请参阅 Wiki on Software Framework。
因此,在 iOS 上,您唯一的选择基本上是使用静态库或静态框架(主要区别在于静态框架最常作为已编译的 .a
文件分发,而静态库可能只是作为子项目包含 -您可以看到所有代码 - 首先编译,其生成的 .a
文件用作项目的依赖项)。
现在我们已经清楚(呃)这些术语了,为 iOS 设置一个静态库和支持媒体包并不难,并且有很多关于如何做到这一点的教程。我个人会推荐这个:
https://github.com/jverkoey/iOS-Framework
这是一个非常直接的指南,没有处理“假静态库”的缺点......查看更多信息......
创建静态库后,只需将其作为子模块包含在 Git 中,以便在不同项目中使用即可。
祝你好运。
编辑
关于项目中的子项目,据我所知,要使其正常工作/编译,您基本上必须设置一个编译链,首先编译子项目,这会创建一个静态框架.a
文件用作项目的依赖项。
这是另一个有用的教程,它讨论了这个:
http://www.cocoanetics.com/2011/12/sub-projects-in-xcode/
编辑 2
从 iOS 8 开始,Apple 现在允许开发人员创建动态框架! (注意:您的应用程序的最低目标必须是 iOS 8 才能包含动态框架……不允许向后移植。)
这已作为新的项目模板添加。在 Xcode 6.1 中,可以在以下位置找到:
New Project -> iOS -> Framework & Library -> Cocoa Touch Framework
Mach-O 文件格式(Mach 对象 - .o
)
在 iOS 世界中,每个源文件都会转换为目标文件 - ABI[About] Mach-O 文件[About],它将被打包成最终的可执行bundle(应用程序、框架)、文件< /strong>(库),其行为由 Mach-O type
[About]
Package
是一个目录,其行为本身就是一个文件 - opaque file
。它是为用户体验而创建的,以使对内部结构进行一些更改变得复杂,这可能导致不可预测的程序行为。包用于 Document Package
或与 Bundle
一起使用。您可以在 Finder 中使用 Show Package Contents
Bundle
是一个具有特定结构的目录,用于组织二进制文件(可执行代码)和该代码的资源(例如图像、笔尖... Assets.car 文件[About])。 Bundle 包含 Info.plist
[About] 文件。 Bundle 是为开发者体验而创建的。也可以打包。有几种类型的捆绑包:
应用程序包 - 应用程序目标
框架包和版本化包作为子类型 - 框架目标
可加载包(又名插件包) - '... Bundle'(UI 测试包,单元测试包) - 可以在运行时加载。 Mac OS 的 .bundle 扩展名
[Mac OS] XPC Service - Cross Process Communication 是一种进程间通信(IPC)。它可以用作不同进程上的模块(由launchd根进程管理)[关于]
其他(dSYM[关于] 捆绑包)
Application
- .ipa
、.app
[About] - packaged
application bundle
- 可启动程序。
Application extension
[About] - 来自 iOS v8 - 扩展了应用程序的功能,这些功能在用户与其他应用程序交互时可用。 App extension
作为捆绑包是 Containing app
的一部分,但它在自己的沙箱(处理器、内存...)上运行,尝试使用 app extension
的应用程序称为 Host App
。扩展应用程序的类型:
行动
分享
照片编辑
今天又名小部件
...
共享通用代码和资源。部署目标为 iOS 8+ 时可用。
Tests
- packaged
loadable bundle
用于测试二进制文件。插件架构允许我们将新功能(测试用例)作为单独的模块添加到现有二进制文件中
库和框架
Martin Fowler on InversionOfControl
库本质上是一组可以调用的函数,现在通常组织成类。每个调用都会做一些工作并将控制权返回给客户端。框架体现了一些抽象设计,内置了更多行为。为了使用它,您需要通过子类化或插入您自己的类将您的行为插入到框架中的各个位置。然后,框架的代码会在这些点调用您的代码。程序的主要控制是倒置的,从你移到框架上。这种现象就是控制反转(也称为好莱坞原则 - “不要打电话给我们,我们会打电话给你”
iOS 上的库和框架
它们可以帮助您解决:模块化、重用、封装、缩短构建时间
Library
是为一个或多个架构编译的 Mach-O 对象文件的集合[check static or dynamic]。
Static library
- .a
(又名静态存档库,静态链接共享库[doc]) - 当您将其添加到您的应用程序中时,编译时期间的静态链接器将合并库中的目标文件并将它们与应用程序目标文件一起打包成一个单独的可执行文件。缺点是输出文件大
从 Xcode 9.0 开始,支持 Swift 静态库。
Dynamic library
- .dylib
(又名动态共享库、共享对象、动态链接库[doc])在加载或运行时与应用的可执行文件动态链接,但没有复制进去。在练习应用程序的包将包含带有 .dylib
文件的 Frameworks 文件夹。所有 iOS 和 macOS system 库都是 dynamic
。缺点是启动时间很慢,因为所有动态库都应该被复制和链接。
Text-based stub library
- .tbd
[About],它是位于目标设备上的 dynamic library
的文本存根。因此,您不应该将动态库打包到您的包中。它具有尺寸效应。
Framework
aka binary framework
- .framework
是一个 not packaged framework bundle
(允许开发人员轻松查看标头和资源),其中包含已编译的 static or dynamic
库、标头文件和资源。
Static framework
包含一个与其资源打包在一起的 static library
。
Dynamic framework
aka Embedded framework
- 来自 iOS v8 - 包含 dynamic library
和资源。除此之外,动态框架可以在单个捆绑包中包含同一动态库的不同版本 (versioned bundle
)。 Embedded framework
也用于 App Extension
Umbrella framework
[Aggregate target] 是一个包含其他框架的框架。它在 iOS 上不受官方支持,因此不建议开发者创建它们[Official doc]。实际上,它是一组子框架(或嵌套框架)。当您创建具有依赖项的框架时,消费者(例如应用程序)负责将此依赖项与您的框架一起添加到项目中。作为开发人员,很自然地尝试找到一种方法将这一职责从消费者转移到您的职责。因此,您认为 Umbrella framework
是一种解救方法,但它通常会导致管理版本以及创建和支持它的复杂性方面出现严重问题。
Fake Framework
- 是在 static library
下的特定操作的结果,用于创建带有 .framework
扩展的捆绑包,其行为类似于 dynamic framework
。当 Xcode 不支持创建框架时使用此技术,因为没有框架模板。 fake framework的实现之一。在 Xcode 6 中,Apple 添加了 iOS 框架支持。
Modular Framework
[About] - @import
它是一个框架,其中包含一个 .modulemap
文件。模块可以包含子模块。主要优点是使用 Modular Framework
可以节省构建时间。
Universal Library or Framework
(又名 Fat)[lipo] [Aggregate target] 包含多种架构。例如,您的发布版本应该支持某个拱门,您可以通过 Build Active Architecture Only
[ONLY_ACTIVE_ARCH] 对其进行调节
XCFramework
[About] 由 Xcode 11 引入,它是一个 bundle
,包括多种架构(arm、x86_64...)和平台(iOS、MacOS...)。它应该替换 Universal Framework
Dependency
[About]您可以使用第三方代码作为目标的一部分。它允许您重用来自许多来源的代码,例如 - 另一个项目、同一工作区中的项目、另一个目标、库、框架等。
如何构建和使用静态库:
[Swift 消费者 -> Swift 静态库]
[Swift 消费者 -> Objective-C 静态库]
[Objective-C 消费者 -> Swift 静态库]
[Objective-C 消费者 -> Objective-C 静态库]
如何构建和使用动态框架[change to static]
[Swift 消费者 -> Swift 动态框架]
[Swift 消费者 -> Objective-C 动态框架]
[Objective-C 消费者 -> Swift 动态框架]
【Objective-C消费者->Objective-C动态框架】
[Xcode Build System]
[Xcode components]
[Dynamic linker]
您还可以为 CocoaPods( http://guides.cocoapods.org/making/private-cocoapods.html#1.-create-a-private-spec-repo ) 创建 .podspec 文件并像使用任何其他 pod 一样使用它,唯一的区别是它是您的私有 pod 并且对外界不可见(我不确定如果您的 pod 应该创建 CoreData 模型,但据我了解,情况并非如此)。