-
- 1.1. Intro
- 1.2. Motivation
- 1.3. External Dependencies
- 1.4. Architecture
- 1.5. Setting up the workspace
- 1.6. Creating a module.
- 1.7. Adding a Module as a Dependency of the App.
- 1.8. Adding inter-module dependencies.
- 1.9. Conclusion
1. Modular Architecture in iOS - Part 1
1.1. Intro
在大型项目中,以及任何项目中,独立创建、运行和测试部件的能力都是必要的。一个部分的改变不应该要求重新编译整个应用程序,直到它确实需要。
在本文中,我将解释如何使用Cocoapods和Xcode创建模块化架构。
就像这样:

1.2. Motivation
想象一下,我们需要在屏幕上做一个小的改变,并尝试它,看看这个改变是否有效。如果我们正在开发的应用程序是作为单个产品独立构建的,那么我们将需要重新编译整个代码库以查看结果。这个过程既费时又乏味。我们应该能够独立地编译和运行部分。
有时,应用程序的一部分非常复杂和庞大,足以被单独视为产品。我们可以称之为模块。模块化是实现可伸缩和随时间推移而维护的软件的关键。
尽管它可能在项目的开始时添加复杂性,从长远来看,我们以模块化的解决方案可能会发现很多好处:更改后重新编译时更少的构建时间,清晰的开发区域/责任,isolation of changes,能够使用playgrounds来构建和测试界面,等等。
1.3. External Dependencies
如今,大多数iOS应用程序都使用Cocoapods或Carthage作为外部依赖管理器。这篇文章的重点是Cocoapods,但这种方法也可以用于Carthage。
据我所知,最重要的区别是,在干净的构建中,Carthage可能产生更低的编译时间。Carthage在应用的构建阶段之外编译框架,只有当我们运行update或install时。
我还没有尝试过Xcode 11、iOS13和Swift Package Manager。似乎用这样的工具构建一个模块化的体系结构是很容易的。这可能是事实,但所有的应用程序都能针对iOS 13拥有这些功能还需要一段时间。所以,Cocoapods和Carthage还会在这里待上一段时间。
那么,我们如何使用Cocoapods作为依赖管理器来实现模块化呢?
1.4. Architecture
该方法包含一个包含多个项目的工作空间。一个项目为最终产品(应用程序)和一个项目为每个模块。应用程序依赖于模块,而模块也可以相互依赖。最后,Cocoapods提供外部依赖。

每个模块编译为目标应用程使用的框架。模块可以相互依赖(虽然没有循环依赖),也可以依赖由Cocoapods处理的第三方sdk。
我们在一个Podfile中定义了外部依赖关系。当我们安装pods时,工作空间将被一个pods项目填充。Pods将输出每个模块和应用程序所依赖的框架。
在下一节中,我将解释如何 创建这样一个结构。
1.5. Setting up the workspace
- 创建一个工作区。
- 为应用程序创建一个项目。
- 初始化Cocoapods和命名的应用程序 依赖关系。
- 将PodIle放在根级 工作区,工作区Ile所在的位置。
- (可选)我喜欢PodIle和 PodIle。锁在工作空间内。
- (可选)我喜欢有一个操场 每个模块都要尝试一下。
- 确保应用程序编译和使用 外部依赖。
工作空间看起来应该像这样:

1.6. Creating a module.
- 创建一个项目,并将其放在 工作区。
- 将模块的依赖项添加到 Podfile。
- 将步骤2的依赖项也添加到应用程序的pods中。
- 运行pod安装并编译模块,以确保它可以使用外部依赖项。
- 添加模块作为项目的依赖项(请参见添加 模块作为App的依赖项)。
At this time, your Workspace, PodIle, and
Folder structure should look like this:

1.7. Adding a Module as a Dependency of the App.
-
创建一个没有文件夹的组,并命名为“Dependencies”或任何你喜欢的名称。
-
将要依赖的项目拖到上一步中创建的组中。
-
(仅第一次)创建一个复制文件构建阶段到框架 - Create a Copy Files Build Phase to Frameworks
-
将框架产品添加到第3步中创建的复制框架构建阶段。

1.8. Adding inter-module dependencies.
当一个模块依赖于另一个内部模块时,请执行此操作。例如,Feature X依赖于Core。
- In the target module (Feature X), create a group without folder and name it “Dependencies” or whatever you like.
- Drag the project you want to depend upon (Core) to the group created in the previous step.
- Drag the framework product to the embedded binaries
- Add the framework product to the copy frameworks build phase created in step 3.
1.9. Conclusion
我认为,不仅大型项目可以从这种架构中获益。能够编译应用的独立部分并在不同的playgrounds运行它们确实是非常棒的。这并不难实现,而且随着时间的推移,你可以享受到好处。
一旦你掌握了诀窍,配置Xcode工作区来使用模块并不复杂。这种方法也可以用于新项目和现有项目中。
这种模块化的影响超过了单纯的实用性,改变了我们内部设计和编码的方式。当一个对象依赖于不属于特定层或模块的东西时,这就变得很明显了。设计错误变得更加明显,整体质量得到提高。