1. Modular Architecture in iOS - Part 1

1.1. Intro

在大型项目中,以及任何项目中,独立创建、运行和测试部件的能力都是必要的。一个部分的改变不应该要求重新编译整个应用程序,直到它确实需要。

在本文中,我将解释如何使用Cocoapods和Xcode创建模块化架构。

就像这样:

avatar

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提供外部依赖。

avatar

每个模块编译为目标应用程使用的框架。模块可以相互依赖(虽然没有循环依赖),也可以依赖由Cocoapods处理的第三方sdk。

我们在一个Podfile中定义了外部依赖关系。当我们安装pods时,工作空间将被一个pods项目填充。Pods将输出每个模块和应用程序所依赖的框架。

在下一节中,我将解释如何 创建这样一个结构。

1.5. Setting up the workspace

  1. 创建一个工作区。
  2. 为应用程序创建一个项目。
  3. 初始化Cocoapods和命名的应用程序 依赖关系。
  4. 将PodIle放在根级 工作区,工作区Ile所在的位置。
  5. (可选)我喜欢PodIle和 PodIle。锁在工作空间内。
  6. (可选)我喜欢有一个操场 每个模块都要尝试一下。
  7. 确保应用程序编译和使用 外部依赖。

工作空间看起来应该像这样:

avatar

1.6. Creating a module.

  1. 创建一个项目,并将其放在 工作区。
  2. 将模块的依赖项添加到 Podfile。
  3. 将步骤2的依赖项也添加到应用程序的pods中。
  4. 运行pod安装并编译模块,以确保它可以使用外部依赖项。
  5. 添加模块作为项目的依赖项(请参见添加 模块作为App的依赖项)。

At this time, your Workspace, PodIle, and
Folder structure should look like this:

avatar

操作视频

1.7. Adding a Module as a Dependency of the App.

  1. 创建一个没有文件夹的组,并命名为“Dependencies”或任何你喜欢的名称。

  2. 将要依赖的项目拖到上一步中创建的组中。

  3. (仅第一次)创建一个复制文件构建阶段到框架 - Create a Copy Files Build Phase to Frameworks

  4. 将框架产品添加到第3步中创建的复制框架构建阶段。

avatar

操作视频

1.8. Adding inter-module dependencies.

当一个模块依赖于另一个内部模块时,请执行此操作。例如,Feature X依赖于Core。

  1. In the target module (Feature X), create a group without folder and name it “Dependencies” or whatever you like.
  2. Drag the project you want to depend upon (Core) to the group created in the previous step.
  3. Drag the framework product to the embedded binaries
  4. Add the framework product to the copy frameworks build phase created in step 3.

1.9. Conclusion

我认为,不仅大型项目可以从这种架构中获益。能够编译应用的独立部分并在不同的playgrounds运行它们确实是非常棒的。这并不难实现,而且随着时间的推移,你可以享受到好处。

一旦你掌握了诀窍,配置Xcode工作区来使用模块并不复杂。这种方法也可以用于新项目和现有项目中。

这种模块化的影响超过了单纯的实用性,改变了我们内部设计和编码的方式。当一个对象依赖于不属于特定层或模块的东西时,这就变得很明显了。设计错误变得更加明显,整体质量得到提高。

代码地址