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 layer
As well asBase layer
In 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 execute
pod install
2. Create a component
Assume the following modules:
The main project
: Carries the main surface business codeCore
: Exists independently and applies sensitive codes such as encryption and interface requestsBase
Base class encapsulation, extension, basic data processingService
: Service layer, encapsulates business tool classes, such as network layer services, persistence services, etcPods
: Tripartite dependence
The relationship between modules is shown as follows
Next, let’s create a module. Take Core module as an example:
- choose
new -> project -> iOS -> Framework
To create a new module
- Choose the right
Group
和WorkSpace
One caveat here: createdlibrary
In the bestMain project root directory
Next, or follow-uppodfile
performpod install
Error will be reported)
- Will create the
library
theBuild Settings -> Mach-O Type
Change 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
- in
Build Phases -> Headers -> Public
Add the newly created file to public so that the main project can access it
- In the main project, choose
target -> Linked Frameworks Library
addCJLCore
The 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/repos
directory
pod repo add mySpecs https://github.com/xxx/MySpecs.git
Copy the code
2. Create Pods projects, or componentization projects
- Create using a terminal
CJLServices
The 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 to
CJLServices -> Classes
In the
- perform
pod 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 them
s.dependency
s.dependency 'AFNetworking'
Copy the code
- If modules need to reference each other, the same configuration is required
s.dependency
In order toCJLBase
For 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 module
Assets
Folder to add resource files - 2, in
specs
To configure the resource path (must!! Otherwise the resource cannot be read.) - 3. Specify the path of the resource file
- 1, in the module
// 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 lib
It’s equivalent to verifying only one local repository,pod spec
Both 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
- perform
pod install
Can be
Refer to the link
- Building a complete iOS componentization solution: How to decouple modules for interfaces
- Modular development practice based on Swift