iOS应用的轻量级模块化

您编写一个应用程序。 首先,它只是一个简单的应用程序。 随着时间的流逝,您会发现许多有用的功能,这些功能将吸引更多的用户并很好地为当前用户服务。 您会找到一个很好的模式来模块化您的应用程序,只需在您的可执行目标模块中放置一个类即可。 设计良好,但不能防错。 幸运的是,错误随着编译时间的增加而上升。 坏消息是,您编写了受错误影响的一千行代码。 那是另一个故事。

这是我构建名为穆斯林应用程序的应用程序时的一些注意事项。 这是一个应用程序,您可能会发现“很多”子应用程序。 就像Google带有其子应用程序(Gmail,文档等)一样。

我将回教应用程序构建为其子应用程序的启动器,其中一些子项是回教笔记(muNote),回教工作(muJob)和回教议程(muAgenda)。 从开发人员角度来看,该应用程序的目标非常简单,您构建的应用程序可以轻松组成更大的应用程序,也可以作为单个应用程序轻松发布。

让我们将这些要求放到一个虚构的讲故事设计中。

  1. 首先,您需要概括这些子应用程序中的通用组件,以使其可以组合成一个应用程序。 您声明将由这些子应用程序实现的协议。 您声明的协议将为“ SubApplication”。
  2. 您实现了一个设计,穆斯林应用程序(将被称为“容器”)将依赖于此协议来启动其子应用程序。
  3. 最后,将这些分散的应用程序连接起来,发现您的设计至少是干净的,可组合的。 一旦需要添加更多子应用程序,就可以实现协议并将其注册到Container。 而且,您仍然可以将单个应用程序作为单个应用程序启动。 如果您与团队一起工作,您会发现开发变得更容易,因为您不需要依靠其他人来测试您自己的工作。

那么,告诉我您的实施情况,男孩!
啊,好吧!

Xcodeworkspace是将另一个文档分组的文档,因此您可以一起处理它们。 这是您可能想知道的第一件事。 因为我正在使用这种工作空间方法,所以我假设您知道这一点。 还有其他方法,但是我现在将继续使用xcodeworkspace。

文档是您最好的朋友!

在继续之前,最好记住本文中使用的术语可能与您先前的理解相抵触。 如果这些冲突使您感到困惑,请记住,本文中的术语受其上下文约束,这意味着当前的目的是模块化。

回想一下我们的要求,它需要一个协议,该协议可以作为Container启动其子应用程序的网关。 您将创建一个有两个主要目标的项目,一个可执行的iOS Single View Application和一个CocoaTouch框架。 您的项目将命名为MuslimApp(容器)。

您可能希望在项目创建时选择“单一视图应用程序”,因为该名称也将是您的xcodeproject文档的名称。

要创建一个新目标,请选择“文件”>“新建”>“目标…”,然后选择一个CocoaTouch框架。 将您的新目标命名为“ SubApplication”,如下所示。 您将在此目标(模块)中声明网关协议。

是的,您已经完成了将Container及其子应用程序网关模块化的第一步。 您可能会好奇,将网关协议放在单独的目标(模块)中可以帮助您为项目定义清晰的结构。 而且,由于SubApplication模块(将称为Gateway)是轻量级的,因此毫无疑问,您可以将其导入到子应用程序中。

Swift采用了面向协议的编程范例,您会想知道它有多么强大。 因此,让我们先声明您的网关协议!

 公共协议SubApplication {} 

由于Swift访问修饰符基于模块作用域起作用,因此在这里使用public。 Public修饰符使您的类型在另一个模块中可见。

下表列出了子应用程序的一般要求:
1.姓名
2.缩略图
3.入门

名称是您的应用程序名称,回教笔记等。
缩略图通常是您的应用程序图标,但您可以选择自己的缩略图。
入门就像容器如何跳转以导航到子应用程序一样。

因为您可能会问启动器的实现是什么,所以这是网关协议的下一个。

由于iOS应用程序将依赖UIViewController机制在屏幕之间进行导航,因此您的入门者将是UIViewController对象。 您可能要使用Navigator模式,但是现在,将不考虑Navigator模式的实现。 为了方便跟随!

由于您具有网关,因此需要它的“消费者”。 网关就像消费者和生产者都知道的API。

该图说明了该设计:

消费者<网关<生产者

您的使用者Container将只知道有一组对象实现了网关,Container的职责只是根据需要使用公共接口。 容器不需要知道如何提供启动器,因为它已经提升为网关实施者。

让我们将代码变成真实的。

您可以使用AppLauncherViewController提供一个控制器来显示子应用程序列表。 为了快速进行原型制作,UITableViewController的子类效果最好。
您提供与网关实施者实例直接交互的Application类。 接下来将介绍。

有多种方法可以定义网关的实现。 怎么可能

假设您对每个子应用程序使用不同的UI体系结构设计(这也是模块化的好处),您将在MVC,MVP,VIPER,Rx + MVVM,Redux等中实现不同的实现。您对Uber的Riblet感兴趣吗?

但是为了简便起见,当前的实现将坚持使Application符合SubApplication协议。

在继续之前,让我们回顾一下SubApplication的需求:

  1. 对于更大的应用程序,它必须是可组合的。
  2. 它必须能够自行释放。

这意味着,我们必须将子应用程序设计为具有自己的可执行目标以及可导入模块。 有趣!

首先,为子应用程序创建一个新项目-Islamic Note-与为穆斯林应用程序创建方法相同。 但是,现在,您将使CocoaTouch框架目标名为IslamicNote,并把可执行目标命名为IslamicNoteApp。

让我们在穆斯林笔记模块中导入SubApplication模块,并使其与MuslimNote.Application保持一致。

申请将负责两个目的。 它的start(window:)方法将从IslamicNote.AppDelegate调用,并且SubApplication实现将满足Container — MuslimApp —的要求。

现在,您已经有了模块化应用程序的基本框架。 您有容器,网关和网关实施程序。 您的实施者还能够运行自己的可执行文件,因此,如果您的团队想要添加新的实施者,则无需构建大型应用程序就可以看到自己的实施者正常工作。 您也可以根据需要发布自己的文件。

该成分将在“容器应用程序”中。 在此之前,请确保您将IslamicNote导入MosqueApp

并要启动它,请使用AppLaucherViewController中的starter属性

真好!

对于每个基于包的对象,您需要通过指定其包来实例化。 请参阅IslamicNote.HomeController实例化。 您可以轻松地成为帮手!

随时在评论部分添加您的意见。