ios模块化、组件化区别
(Modular iOS)
Are you looking to reuse code in multiple apps? Or maybe you want to offer some code to your customers to include it in their apps so they can consume your services quicker. Having chunks of reusable code that can be used with multiple apps is called module.
您是否想在多个应用程序中重用代码? 或者,也许您想向客户提供一些代码以将其包含在他们的应用程序中,以便他们可以更快地使用您的服务。 拥有可与多个应用程序一起使用的可重用代码块称为模块。
How do you modularise code? How does modularisation work? Can modules includes images?
您如何模块化代码? 模块化如何工作? 模块可以包含图像吗?
This guide will help you answer the above questions and more. On iOS there is more than one way to modularise code. I will walk you through different options. I’ll cover what the differences are between each of them. Then I’ll look into the options on how to distribute it.
本指南将帮助您回答上述问题以及更多问题。 在iOS上,有多种方法可以对代码进行模块化。 我将引导您完成不同的选择。 我将介绍它们之间的区别。 然后,我将研究如何分发它的选项。
I will not go in depth with how-to steps. There will be no coding involved in this guide. My aim with this guide is to help you see the larger picture and point you into the right direction. I have written tutorials on with detailed steps on how to build, package and distribute modules on iOS for the different options. I will provide links throughout this guide and at the end of it.
我不会深入介绍操作步骤。 本指南将不涉及任何编码。 本指南的目的是帮助您查看大图,并为您指明正确的方向。 我编写了教程,其中包含有关如何在iOS上针对不同选项构建,打包和分发模块的详细步骤。 我将在本指南的整个结尾处提供链接。
In this post I will cover:
在这篇文章中,我将介绍:
- What a module is
- Why modularise your code
- Why not to modularise your code
- Modularisation options
- Packaging options to prepare your module for distribution
- Distribution options for your module
For this post I assume you are comfortable with iOS development and programming in general. You should have a basic understanding of how apps works in the iOS ecosystem.
对于本文,我认为您通常对iOS开发和编程感到满意。 您应基本了解应用程序在iOS生态系统中的工作方式。
(What is a module?)
In simple terms its a package that contains code. Some options allow resources such as images to be included too.
简单来说,它是一个包含代码的包。 一些选项还允许包括图像之类的资源。
For example you may want to separate your login screen into a separate module. The module will include the code and resources to launch and display the login screen. The module will also include images used in the login screen. The app can then include the login module. Subsequently the app can then load and display the login screen from the module when needed.
例如,您可能想将登录屏幕分为一个单独的模块。 该模块将包含启动和显示登录屏幕的代码和资源。 该模块还将包括登录屏幕中使用的图像。 然后,该应用可以包括登录模块。 随后,该应用随后可以在需要时从模块加载并显示登录屏幕。
(Why Modularise?)
You may be asking why should I break my code into modules? There are many reasons. Here is a non-exhaustive list of reasons why you should modularise code:
您可能会问为什么我应该将代码分成模块? 原因有很多。 这是您应该模块化代码的原因的详尽列表:
(Reuse of code)
If you’d like to use some code in more than one app or target then modularising your code will allow you to share easily your code with these separate apps.
如果您想在多个应用程序或目标中使用某些代码,那么对代码进行模块化将使您可以轻松地与这些单独的应用程序共享代码。
Reusing code means that the code needs to updated only in one place. Alternatively you can copy and paste code from project to project. However if your code contains bugs then you’ll have to fix the bug across all of your projects. This can lead a higher maintenance cost.
重用代码意味着只需要在一个地方更新代码。 或者,您可以在项目之间复制和粘贴代码。 但是,如果您的代码包含错误,则必须在所有项目中修复该错误。 这会导致更高的维护成本。
(Going public)
Modularisation allows you to share parts of your apps code publicly for others to consume and change. This isn’t an option for everyone.
模块化允许您公开共享应用程序代码的一部分,以供其他人使用和更改。 这不是每个人的选择。
However if the code is not core to your business and others are replicating the same code then modularising and going public can allow you to share the maintenance burden with other developers.
但是,如果代码不是您业务的核心,而其他人正在复制同一代码,则模块化并公开发布可以使您与其他开发人员分担维护负担。
Furthermore other developers might even add features to the module which you could consume for free.
此外,其他开发人员甚至可能向模块添加功能,您可以免费使用这些功能。
Another reason is that your business offers services to other app builders to consume. Instead of having each of your customer producing the code to consume your services, you can have them consume some already packaged code. This will allow them to start consuming your services faster and you’ll start making money earlier!
另一个原因是您的企业向其他应用程序构建者提供服务以供使用。 您可以让他们使用一些已经打包的代码,而不是让每个客户都产生使用服务的代码。 这将使他们能够更快地开始使用您的服务,并且您将更早开始赚钱!
(Separation of concerns)
Different parts of your app will have different reasons to change. For example when you change your authentication methods then only the authentication code needs to change.
应用程序的不同部分将具有不同的更改原因。 例如,当您更改身份验证方法时,只需更改身份验证代码。
(Encapsulation)
Some parts of your code are meant to be consumed by only one class or a set of classes that are related to the code.
代码的某些部分只能由与该代码相关的一个或一组类使用。
When your code lives within the main app other parts of the code have access to the code that they are not meant to be using. Sometimes developers can make mistakes and use code from places they are not intended to. This could leads to bugs or code entanglements.
当您的代码位于主应用程序中时,代码的其他部分可以访问它们不打算使用的代码。 有时,开发人员可能会犯错误,并在不希望的地方使用代码。 这可能会导致错误或代码纠缠。
Modularisation can keep code private to other parts of the app that are not intended to be using this code.
模块化可以使代码对应用程序的其他部分(不打算使用此代码)保持私有。
(Speeding up build time)
Building your project from scratch means rebuilding code that is unchanged or not meant to change as part of your app. Re-compiling code that does not change can increase your compilation time as your app grows larger and more complex.
从头开始构建项目意味着重新构建未更改的代码或不打算在应用程序中进行更改的代码。 随着应用程序变得更大和更复杂,重新编译不变的代码可能会增加编译时间。
However modularising your code and consuming compiled modules can speed up your build times significantly. Compiled modules means that when your app code builds from scratch then only the app code will be compiled and not the module. Thus reducing the amount of code compilation on any given project.
但是,将代码模块化和使用已编译的模块可以显着加快构建时间。 编译模块意味着从头构建应用程序代码时,仅应用程序代码将被编译,而不是模块。 这样就减少了任何给定项目上的代码编译量。
(Why you shouldn’t modularise your code?)
Modularization has some drawbacks. These should be taken into account before deciding whether to modularize your code. Here are some reasons why you shouldn’t modularise your code:
模块化具有一些缺点。 在决定是否对代码进行模块化之前,应考虑这些因素。 以下是您不应该模块化代码的一些原因:
(Complexity)
First the process of modularising your code can be complex. First you need to extract the code where it is used. Then you need to package and distribute this code. Finally you’ll need to make sure where the module code is used the proper import statement is declared to use that package.
首先,模块化代码的过程可能很复杂。 首先,您需要提取使用代码。 然后,您需要打包并分发此代码。 最后,您需要确保在哪里使用了模块代码,并声明了正确的import语句以使用该程序包。
Furthermore if your module has shared code with your app then you might be required to modularised the shared code too.
此外,如果您的模块已与您的应用共享代码,则可能还需要模块化共享代码。
(Overhead costs)
Some feature developments might require changes in multiple modules as well as the app consuming it. This may increase the cost of development for some features.
一些功能开发可能需要更改多个模块以及使用该模块的应用程序。 这可能会增加某些功能的开发成本。
(Increasing launch time)
This point requires some understanding about how modules works on iOS.
这一点需要一些关于模块如何在iOS上工作的理解。
Having too many dynamic frameworks — one of the modularisation options — can slow down the launch time of your app.
动态框架过多(模块化选项之一)会减慢应用程序的启动时间。
(Modularisation options for iOS)
There are 2 ways to distribute modular code for iOS:
有两种方式为iOS分发模块化代码:
- dynamic frameworks 动态框架
- static libraries 静态库
The option you choose can have different implications for your how your module code runs. Let’s see how each of these work and then compare them.
您选择的选项可能会对模块代码的运行方式产生不同的影响。 让我们看看这些功能如何工作,然后进行比较。
动态框架 (Dynamic frameworks)
A framework is a structured directory that can contain shared code and shared resources such images, nibs (compiled form of xibs and storyboards) and other assets.
框架是一个结构化目录,可以包含共享代码和共享资源,例如图像,笔尖(XIB和情节提要的组合形式)和其他资产。
Anatomy of a framework 框架剖析
The framework lives separately to the app and is loaded separately too. The system loads the app which in turns tells the system that it requires to consume the framework code to run. The system then loads the framework that the app relies on. All of this happens at runtime.
该框架单独存在于应用程序中,并且也单独加载。 系统会加载应用程序,该应用程序又会告诉系统它需要消耗框架代码才能运行。 然后,系统加载应用程序所依赖的框架。 所有这些都在运行时发生。
Loading framework packaged with app
加载与应用程序打包在一起的框架
静态库 (Static Libraries)
A static library is a collection of compiled source code files. Let’s say we have FileA.swift, FileB.swift and FileC.swift. With a static library we can compile these files and wrap them inside a single file containing all of these. The file has has an extension of .a; short for archive. Sort of like getting some pages and making a book out of it.
静态库是已编译源代码文件的集合。 假设我们有FileA.swift , FileB.swift和FileC.swift 。 使用静态库,我们可以编译这些文件并将它们包装在包含所有这些文件的单个文件中。 该文件的扩展名为.a ; 存档的缩写。 有点像获取一些页面并制作一本书。
Static library compilation representation
静态库编译表示
When our app consumes code statically the code that it consumes gets copied into the app executable binary.
当我们的应用静态使用代码时,它消耗的代码将复制到应用可执行二进制文件中。
Linking static library to your app 将静态库链接到您的应用
When the system loads the app, the static library functionality is loaded with it as single executable.
当系统加载应用程序时,静态库功能将作为单个可执行文件一起加载。
iOS loading app containing static library 包含静态库的iOS加载应用
(What is the difference between static libraries and dynamic frameworks?)
Static Libraries are loaded with the app which could lead to faster app launch times.
静态库已随应用程序一起加载,这可能会加快应用程序的启动时间。
Static Libraries can’t have resources included within. These can still be imported separately using bundles. However it requires delivering an additional artefact.
静态库不能包含资源。 这些仍然可以使用捆绑包单独导入。 然而,这需要传递额外的人工制品。
Dynamic libraries are loaded separately and can have slower app launch times.
动态库是单独加载的,可能会使应用启动时间变慢。
Dynamic libraries can include resources.
动态库可以包含资源。
(How to package your iOS module for distribution)
There are multiple ways of packaging your iOS module for distribution. Packaging options include:
打包iOS模块以进行分发有多种方法。 包装选项包括:
(Open code)
This when you deliver your code to the consumer. The code is accessible and readable. The code gets compiled on the consumers machine along with their code.
这是在您将代码交付给使用者时。 该代码是可访问且可读的。 该代码连同其代码一起在使用者计算机上编译。
This form doesn’t benefit from faster build time compilation as the code gets rebuilt on every clean build of the consuming app.
这种形式无法从更快的构建时间编译中受益,因为代码会在使用该应用程序的每个干净构建中都重新构建。
Additionally the consumer can make changes to your code.
此外,使用者可以更改您的代码。
(Compiled)
The module code gets compiled and then distributed. The consumer uses the compiled form. The consumer will not be able to read and modify the code. The consumer will enjoy faster build times than open code packaging. Furthermore you are able to hide your code.
模块代码被编译然后分发。 消费者使用编译后的表格。 消费者将无法阅读和修改代码。 消费者将比开放代码包装享有更快的构建时间。 此外,您还可以隐藏代码。
Compiling a framework to a .framework or a static library to an archive (.a) will only work with either simulators or devices but not both. There is a way for consumers to have both build variants in a single artefact called XCFrameworks (more on the next section).
将框架编译为.framework或将静态库编译为存档( .a )将仅适用于模拟器或设备,但不适用于两者。 消费者有一种方法可以在称为XCFrameworks的单个工件中拥有这两种构建变体(在下一节中有更多介绍)。
Note there are also hacks to get around supporting simulators and devices without using XCFrameworks (framework and static libraries). However I’d recommend to stick to the Apple supported ways.
请注意,在不使用XCFrameworks( 框架和静态库 )的情况下,也存在一些绕开支持模拟器和设备的技巧。 但是,我建议您坚持使用Apple支持的方法。
(Compiled and packaged as an XCFramework)
XCFramework is a structured directory that can hold multiple build variants of a framework or static library.
XCFramework是一个结构化目录,可以容纳框架或静态库的多个构建变体。
When you compile a static library or dynamic framework the compiled form only works with either simulator or devices but not both.
编译静态库或动态框架时 ,编译后的表单仅适用于模拟器或设备,而不能同时适用于两者。
XCFrameworks allow you to package multiple built variants of your module into a single artefact. That means that within a single package an integrator will be able to use your module with simulators and devices.
XCFrameworks允许您将模块的多个已构建变体打包到单个工件中。 这意味着集成商可以在单个软件包中将模块与模拟器和设备一起使用。
You can learn more on how to build XCFrameworks for frameworks on the post below:
您可以在下面的文章中了解有关如何为框架构建XCFrameworks的更多信息:
You can learn more on how to build XCFrameworks for static libraries on the post below:
您可以在下面的文章中了解有关如何为静态库构建XCFrameworks的更多信息:
(How to distribute your module)
There are multiple options on how to distribute modular code. The distribution depends on the modularisation option and how its packaged. Each distribution method has its own benefits and drawbacks.
关于如何分发模块化代码,有多种选择。 分布取决于模块化选项及其包装方式。 每种分配方法都有其自身的优点和缺点。
Here I will also list out your distribution options for your module with and without additional tools. These additional tools listed here are dependency managers that help to make deploying and integrating with your module easier.
在这里,我还将列出使用和不使用其他工具的模块分发选项。 此处列出的这些其他工具是依赖项管理器,可帮助简化模块的部署和集成。
Let’s take a look at some of the options.
让我们看一些选项。
(Distribution without dependency managers)
Here you have three options:
在这里,您有三个选择:
- Distribute your module Xcode project
- Distribute your module compiled
For the first option the consumer of your framework can state directly the module target as a dependency of their app. This is achieved through an Xcode workspace which can contain one or more Xcode projects in a single Xcode window.
对于第一种选择,框架的使用者可以直接将模块目标声明为其应用程序的依赖项。 这是通过一个Xcode工作区实现的,该工作区可以在一个Xcode窗口中包含一个或多个Xcode项目。
The second option is to compile the module and then distribute it. The consumer downloads the compiled module into their project and links to it directly.
第二种选择是编译模块,然后分发它。 使用者将编译后的模块下载到他们的项目中并直接链接到它。
(Distribution using Cocoapods)
Cocoapods is a popular iOS dependency manager. In simple terms it allows you to specify which dependencies (or modules) your app depends on. Cocoapods takes care of the installation and configuration of these.
Cocoapods是流行的iOS依赖项管理器。 简而言之,它允许您指定应用程序所依赖的依赖项(或模块)。 Cocoapods负责这些的安装和配置。
Again here there are two ways you can distribute your module through Cocoapods:
同样,这里有两种方法可以通过Cocoapods分发模块:
- Distribute your module code
- Distribute your module compiled
The first option tells Cocoapods where your source code lives and the files to include. Cocoapods then fetches the source code and wraps it in a module. The difference with linking directly to the Xcode project is that the integrator has much greater control on the configuration of the project. They can even choose how they would like to link with your code; statically or dynamically. Cocoapods takes care of the rest.
第一个选项告诉Cocoapods您的源代码在哪里以及要包含的文件。 然后,Cocoapods获取源代码并将其包装在模块中。 直接链接到Xcode项目的不同之处在于,集成商对项目的配置具有更大的控制权。 他们甚至可以选择如何与您的代码链接; 静态地或动态地 。 Cocoapods负责其余的工作。
The second option is much similar to installing compiled modules without Cocoapods. However Cocoapods still adds value by allowing greater version control to the integrator. Cocoapods supports distribution of compiled dynamic frameworks, compiled dynamic frameworks packaged as XCFrameworks, compiled static frameworks and static libraries as XCFrameworks.
第二个选项与不带Cocoapods的已编译模块的安装非常相似。 但是,Cocoapods仍然可以通过允许集成商更好地控制版本来增加价值。 Cocoapods支持分发已编译的动态框架 , 打包为XCFrameworks的已编译动态框架 ,已编译的静态框架和已编译为XCFrameworks的静态库 。
(Distribution using Swift Package Manager)
Swift Package Manger (SPM) is the latest dependency manager to join the party. Swift Package Manager is that it is included with Swift and is maintained by the Swift community.
Swift Package Manger(SPM)是加入聚会的最新依赖管理器。 Swift Package Manager包含在Swift中,由Swift社区维护。
Similarly to Cocoapods, SPM relies on package specification file that tells the consumer end how to install and link to the package.
与Cocoapods相似,SPM依赖于软件包规范文件,该文件告诉用户端如何安装和链接到软件包。
There are two way to distribute your module however with some limtations:
分发模块有两种方法,但有一些限制:
- Distribute your code as a static library 将您的代码作为静态库分发
- Distribute your module compiled
Note for the first option at the time of writing you can only distribute code without resources. Furthermore dynamic linking for iOS is not supported.
请注意,在编写本文时,第一个选项只能分发没有资源的代码。 此外,不支持iOS动态链接。
The second option is to distribute your module compiled. This is similar to Cocoapods. The difference is that Swift Package Manager does not support the distribution of archives (.a) and frameworks (.framework). However it does support the distribution of XCFrameworks for both static libraries and dynamic frameworks.
第二种选择是分发已编译的模块。 这类似于可可足类。 区别在于,Swift Package Manager不支持档案( .a )和框架( .framework )的分发。 但是,它的确支持为静态库和动态框架分发XCFrameworks。
(Distribution using Carthage)
The final popular option for iOS dependency manager although the least popular option from the list is Carthage.
iOS依赖项管理器的最后一个流行选项,尽管列表中最不流行的选项是Carthage 。
Carthage is very different to the first two options. It does not require a module specification file. Alternatively it relies on the Xcode project files to know how to build the module. If the Xcode project specifies dynamic frameworks then the module will be built as universal dynamic framework.
迦太基与前两个选项有很大的不同。 它不需要模块规范文件。 另外,它依靠Xcode项目文件来知道如何构建模块。 如果Xcode项目指定了动态框架,则该模块将被构建为通用动态框架。
Carthage only fetches and builds the dependencies for you. It does not link the compiled module to the consuming app project. That is up to the consumer of the module to do.
迦太基只为您获取并构建依赖项。 它不会将编译后的模块链接到使用中的应用程序项目。 这取决于模块的使用者要做。
If the module is already compiled then it only fetches the compiled artefact for you.
如果模块已经被编译,那么它只会为您获取已编译的工件。
Carthage is a great option for those wanting a very simple solution to their dependency management needs. Carthage can also work with projects that are not intended to support Carthage.
对于那些想要一个非常简单的解决方案来解决依赖管理需求的人来说,迦太基是一个不错的选择。 迦太基还可以与不支持迦太基的项目一起工作。
However it being the least popular means that it is the slowest to get updates and bug fixes.
但是,它是最不流行的,意味着它是最慢的更新和错误修复程序。
(Final Notes)
I have included links to earlier tutorials where I explain step by step of different ways to package and distribute iOS code. Below you can find the full list:
我提供了一些以前的教程的链接,其中逐步解释了打包和分发iOS代码的不同方法。 您可以在下面找到完整列表:
(Frameworks)
- Reusing code with Swift frameworks 在Swift框架中重用代码
- Distributing Swift Frameworks via Cocoapods 通过Cocoapods分发Swift框架
- How to build universal iOS frameworks for distribution 如何构建通用的iOS框架进行分发
- Distributing Compiled Swift Frameworks via Cocoapods 通过Cocoapods分发编译的Swift框架
- How to distribute iOS frameworks using Carthage 如何使用Carthage分发iOS框架
- How to build universal iOS frameworks using XCFrameworks 如何使用XCFrameworks构建通用的iOS框架
- How to distribute compiled iOS frameworks using Swift Package Manager 如何使用Swift Package Manager分发已编译的iOS框架
- Distributing universal iOS frameworks as XCFrameworks using Cocoapods 使用Cocoapods将通用iOS框架作为XCFrameworks分发
(Static Libraries)
- Reusing code and resources with Swift static libraries and resource bundles 通过Swift静态库和资源包重用代码和资源
- Distributing compiled iOS Swift static libraries and Swift static frameworks 分发已编译的iOS Swift静态库和Swift静态框架
- How to distribute compiled static frameworks via Cocoapods 如何通过Cocoapods分发已编译的静态框架
- How to Distribute iOS Libraries With Swift Package Manager 如何使用Swift Package Manager分发iOS库
- How to build universal iOS static libraries using XCFramework 如何使用XCFramework构建通用的iOS静态库
Stay tuned for more on iOS development! Follow me on Twitter or Medium.
翻译自: https://medium.com/@anuragajwani/modular-ios-guide-60810f5a7f97
ios模块化、组件化区别