IOS underlying principles article summary

This article focuses on two options for componentization

componentization

In fact, componentization is a way to separate modules, layer them, and specify the communication mode between modules, so as to realize decoupling. It is mainly used and developed by teams

Why is componentization needed?

There are four main reasons

  • 1. Decoupling between modules

  • Module reuse

  • 3. Improve the efficiency of team cooperation and development

  • 4. Unit testing

When the project gets more and more due to various requirements, if the modules are calling each other, that is, I have me, I have you, this will cause a high coupling situation. Every time we need to change a piece of code, it will change everything, making the project difficult to maintain

Its problems are mainly reflected in the following aspects:

  • 1. When you modify a function, you need to modify the code of other modules at the same time, because there are references to the module in other modules. It can be understood that high coupling makes code modification difficult

  • 2. The external interface of the module is not clear, and even the private interface that should not be exposed is exposed. The modification is time-consuming and laborious. It can be understood that the interface is not fixed, resulting in interface chaos

  • 3. The consequence of highly coupled code is that it can affect the development of other team members and cause code conflicts

  • 4. When modules need to be reused in other projects, it is difficult to separate them

  • 5. The restriction of coupling between modules leads to confusion of interfaces and dependencies, and unit tests cannot be carried out

Therefore, in order to solve the above problems, we need to adopt a more standardized way to reduce the coupling degree between modules, which is called componentization, which can also be understood as modularization

One caveat here, however, is that not all projects need to be componentized, since componentization is also costly, taking time to design interfaces, separate code, and so on. Your project does not need componentization if it has the following characteristics:

  • 1. The project is small, the interaction between modules is simple and the coupling is less

  • 2. The project is not referenced by multiple external modules, just a single small module

  • Modules are not reused and the code is rarely changed

  • 4. The team is small

  • 5. You don’t need to write unit tests

If you have the following features, you must consider componentization:

  • 1. The module logic is complex, and multiple modules frequently reference each other

  • 2. As the project gets larger, it becomes more and more difficult to change the code.

  • 3. As the team grows in size, the submitted code often conflicts with other members

  • 4. Project compilation is time-consuming

  • Unit tests of modules often fail due to changes in other modules

Componentization scheme

Eight indicators of componentization scheme

How to evaluate a project after componentization mainly includes the following criteria:

  • 1. Modules are not coupled to each other, and modifications within modules should not be made to other modules
  • Modules can be compiled separately
  • 3. Clear data transfer between modules
  • 4. A module can be replaced at any time by another module that provides the same function
  • 5. The external interface of the module is clear and easy to maintain
  • 6. When the module interface changes, the external code of this module can be reconstructed efficiently
  • 7. Try to modularize existing projects with minimal modifications and code
  • 8. Support OC and Swift, and mix

The first four measures whether a module is truly decoupled, and the last four measures how easy it is to use in practice on a project

Componentization principleA project is divided into three levels:The business layer,General layerAs well asBase layerIn the componentization, there are the following points

  • Only the upper layer can depend on the upper layer, and the lower layer cannot depend on the upper layer, because the lower layer is an abstraction of the upper layer

  • Project common code resources sink

  • Horizontal dependencies should be minimal, preferably down to generic modules, or base modules

Componentization schemes There are two commonly used componentization schemes:

  • Local component: Mainly by creating a library in the project, using Cocoapods workSpec for local management, do not need to upload the project to Git, but directly in the project to the framework method to call

  • Cocoapods componentization: The main use of Cocoapods module remote management, the need to upload the project to Git (need to note: the componentization module is divided into public library and private library, for the company, is generally private library)

Local componentization

1. Create a master project

  • Start by creating a project

  • Cocopods integration for local management:
$CD Project directory $POD InitCopy the code
  • Edit the podfile and executepod install

2. Create a component

Assume the following modules:

  • The main project: Carries the main surface business code
  • Core: Exists independently and applies sensitive codes such as encryption and interface requests
  • BaseBase class encapsulation, extension, basic data processing
  • Service: Service layer, encapsulates business tool classes, such as network layer services, persistence services, etc
  • Pods: Tripartite dependence

The relationship between modules is shown as follows

Next, let’s create a module. Take Core module as an example:

  • choosenew -> project -> iOS -> FrameworkTo create a new module

  • Choose the rightGroupWorkSpaceOne caveat here: createdlibraryIn the bestMain project root directoryNext, or follow-uppodfileperformpod installError will be reported)

  • Will create thelibrarytheBuild Settings -> Mach-O TypeChange to a static libraryStatic Library

3, the main project calls library

  • Create a new file in CJLCore and add the following code
Public class CJLCoreSetting: NSObject {public static let SCRET_KEY = "SCRET_KEY"}Copy the code
  • inBuild Phases -> Headers -> PublicAdd the newly created file to public so that the main project can access it

  • In the main project, choosetarget -> Linked Frameworks LibraryaddCJLCoreThe library can be automatically linked with the main build project

4, the use of

First of all,import CJLCore, and then use

The important thing to note here is that the child libraries call each other, just like the main project calls the library, the main needs to add dependencies and expose headers

5. Use Cocoapods to manage dependencies

Let’s say we need to encapsulate network layer code in CJLCore, using the three-party library Alamofire, in podfile

Platform: ios, '9.0' inhibit_all_warnings! use_frameworks! # configuration workspace path workspace 'Modularization. Xcworkspace' # # # # # # # # # # # # # # # # # # three sides rely on public def workspace_pods pod 'SwiftyJSON' End # def project_only_Pods pod 'SnapKit' end # def network_layer_Pods pod 'Alamofire' end ################# Target 'CJLCore do # project configuration libray path' CJLCore/CJLCore xcodeproj 'workspace_pods network_layer_pods end ################# Main project target 'Modularization' do workspace_Pods project_only_Pods network_layer_Pods Target 'ModularizationTests' do inherit! :search_paths end target 'ModularizationUITests' do end endCopy the code

At this point, a locally componentized module is configured

Cocoapods componentization

In addition to local componentization, you can also usecocoapods, the principle is shown in the following figure

Again, take the structure in local componentization as an example

Create a private repository

  • Create a MySpecs repository on Github

To do this, log in to Github –> click the “+” button in the upper right corner –> Select New Repository –> Enter the Repository name as MySpecs, select the repository type as Private, and click Create Repository.

  • Add a private repository to the local~/.cocoapods/reposdirectory
pod repo add mySpecs https://github.com/xxx/MySpecs.git
Copy the code

2. Create Pods projects, or componentization projects

  • Create using a terminalCJLServicesThe module
pod lib create CJLServices
Copy the code
  • Enter ios, swift, YES, None, no, CJL as prompted

  • Go to the module directory and copy the file toCJLServices -> ClassesIn the

  • performpod install, will update Classes to Pods

3. Configure Pods project

Modify the configuration file of the module, cjLServices.podspec

  • If you need to rely on third-party libraries, you need to configure thems.dependency
s.dependency 'AFNetworking'
Copy the code
  • If modules need to reference each other, the same configuration is requireds.dependencyIn order toCJLBaseFor example, need to quoteCJLService
'CJLServices' //********2. 'CJLServices', :path => '.. /.. /CJLServices'Copy the code
  • If you need to load resources, such as images, JSON, bundle files, etc
    • 1, in the moduleAssetsFolder to add resource files
    • 2, inspecsTo configure the resource path (must!! Otherwise the resource cannot be read.)
    • 3. Specify the path of the resource file
// mysbundles = {'CJLBase' => ['CJLBase/Assets/*']} //***** String = Bundle.init(for: dynamicClass.self).resourcePath! + "/CJLBase.bundle" let bundle = Bundle(path: bundlePath) if let path = bundle? .path(forResource: "mouse", ofType: "jpg"){ self.imgView.image = UIImage(contentsOfFile: path) }Copy the code

Similarly, the xiB and JSON files in the module are obtained in the same way

Commit to Git

In this case, only the Pods project can be submitted to Git. For example, CJLBase

  • Create a private repository on Github named CJLBase

  • Run the following terminal command

$git add origin $git add origin $git add origin $git add origin $git add origin https://github.com/xxx/CJLBase.git $git push origin master / / must have labels, or you will have the following warning / / podspec file access to the git version control projects need the tag number, $git tag -m "first release" "0.1.0" $git pushCopy the code

Verify the PodSpec file

Run the pod spec lint terminal command

Note: The Pod Spec is more accurate than the Pod Lib,

  • pod libIt’s equivalent to verifying only one local repository,
  • pod specBoth local and remote repositories are validated.

6. Submit to a private repository

Run the following command

Pod repo push [local Spec repo name][Path of the Podspec file] //****** For example $pod repo push MySpecs CJLBaseCopy the code

After successful submission, you can see the submit path MySpecs -> CJLBase in the local repository

7, use,

  • Create a new project and add it to the project’s Podfile
Private spec # warehouse address, rather than a single pod warehouse address source 'https://github.com/xxx/MySpecs' pod' CJLBase 'Copy the code
  • performpod installCan be

Refer to the link

  • Building a complete iOS componentization solution: How to decouple modules for interfaces
  • Modular development practice based on Swift