Series of articles:OC Basic principle series.OC Basic knowledge series.Swift bottom exploration series.IOS Advanced advanced series

preface

Originally wanted to write to continue to write interface optimization, but because the previous period of time the project is more busy, has not done! In addition, the recent project is also sorting out the componentization things, so I decided to write an article about componentization.

componentization

When we talk about componentization, the first thing that comes to mind is decoupling and modularization. In fact, componentalization is a way to decouple the modularization from the layer and develop the communication mode between modules, which is mainly used in team development

A little bit of componentization

Componentization has two main advantages

  • 1.Decoupling between modules
  • 2.Module reuse
  • 3.Improve team collaboration and development efficiency
  • 4.Facilitate unit testing

When the project is getting bigger and bigger due to various requirements, if the various modules are calling each other, that is, there is a me in each other, there is a you in each other, this situation will result in high coupling. Once we need to modify a piece of code, it will cause problems with a wide range of influences and multiple functions, which makes it difficult to maintain the project. The problems are mainly reflected in the following aspects

  • 1. When modifying a function, you need to modify the code of other modules because the module is referenced in other modules. Can be understood asHigh coupling makes code modification difficult
  • 2. The external interface of the module is not clear, and even exposes the private interface that should not be exposed, which takes time and effort to modify. Can be understood asInterface confusion caused by unfixed interfaces
  • 3. The consequence of highly coupled code is that it affects the development of the rest of the team,Create code conflicts
  • 4. When modules need to be reused to other projects,It's hard to separate
  • 5. The coupling taboo between modules leads to the confusion of interfaces and dependencies.Unable to unit test

So in order to solve the above problems, we need to adopt a more standardized way to reduce the coupling degree between modules, and then the componentization came into being, componentization can also be understood as modularization

Description of application of componentization

The benefits of componentization are mentioned above, but because componentization is also costly, requiring time to design interfaces, separate code, etc., not all projects need to be componentized. Your project does not need to be componentized if it has three or more of the following characteristics:

  • 1.Smaller projects, simple interaction between modules, less coupling
  • 2. The projectNot referenced by multiple external modules, is just a single little module
  • 3.Modules do not need to be reused.Code is rarely changed
  • 4. Teamsmall
  • 5.No unit tests need to be written

If you have more than three of the following characteristics, you need to consider componentization:

  • 1. The moduleComplex logic, between multiple modulesFrequent cross-references
  • 2. The projectIt's getting bigger.Modify the codeMore and moredifficult(If you change one part of the code, you need to change several other places at the same time.)
  • 3. The teamThe number of moreSubmitted,codeOften with other membersconflict
  • 4. ProjectLarge compilation time
  • 5. The moduleUnit testingOften due toOther modulesModifications andfailure

Componentization scheme

Componentized indicators

How to judge whether the componentization of a project is thorough or excellent after componentization can be judged from the following aspects:

  • 1.There is no coupling between modulesChanges made within a module do not apply to other modules
  • 2.Modules can be compiled separately
  • 3.Clear data transfer between modules
  • 4.The modulecanAt any timeBy another module that provides the same functionalityreplace
  • 5.The external interface of the module is clear and easy to maintain
  • 6. WhenModule interface changeWhen, of this moduleExternal codeIt can beEfficient refactoring
  • 7. As far as possibleWith minimal modifications and codeLet the existingProject implementation modularization
  • Support 8.OC and Swift, and remix

The first four are used to measure whether a module is truly decoupled, while the last four are used to measure how easy it is to use in practice in a project

Principle of componentization

Generally, a project is divided into three levels:The business layer.General layer.Base layer, as shown in the figure below:When componentizing, there are several points to note:

  • 1.Only the top can depend on the bottom.There can be no dependence of the lower on the higherBecause the lower layer is an abstraction from the upper layer
  • 2. The projectCommon code resources sink
  • 3.Horizontal dependencies should be minimized, it is best to follow horizontally· Sink to universal moduleorBasic module

Componentization scheme

Currently, there are two common componentization schemes:

  • 1,Local componentization: Mainly throughCreate the Library in the project, the use ofThe cocoapods workspecforLocal management.Don't needThe projectUpload the git, butdirectlyinProject in framework modeforcall
  • 2.Cocoapods componentization: Mainly usecocoapodsTo carry outThe moduletheRemote management, you need toUpload your project to Git(where theComponentized modulesDivided intoThe public libraryandPrivate librariesforThe company is concerned, usuallyPrivate libraries)

Let’s talk about local componentization

Local componentization

1. Create a main project

  • Create the main project first

  • Integrate Cocopods for local management
$CD Project directory $pod initCopy the code
  • Edit the podfile and execute Pod Install

2. Create a component

Create your own module:

  • The main project: Mainly implements the surface business code
  • BaseBase class encapsulation
  • Tools: tools (strings, colors, fonts, etc.)
  • Service: service layer, which encapsulates business tool classes, such as network layer services and persistence services
  • Pods: Third-party dependencies

The relationship of each module is as follows:Now let’s do a simple module creationServiceFor example:

  • 1. Choose choicesnew -> project -> iOS -> Framework, create a new oneThe module

  • 2. Choose the right oneGroupandWorkSpaceOne thing to note here: the library you createdPreferably in the main project root directoryUnder, otherwise follow-upPodfile receives an error when executing pod Install)

  • 3. To be createdlibrarytheBuild Settings -> Mach-O TypeModified toStatic Library

  • 4. Write the required code in LjComponentA

  • In 5.Build Phases -> Headers -> PublicAdd the newly created file to public so that the main project can access it

  • 6. In the main project, choosetarget -> Linked Binary With LibrariesTo add LjComponentA, only need to build the main project, library can automatically link

  • 7. Main project invocation

The important thing to note here is,Calls between child libraries, andThe main project calls library similarlyThe main needAdd the dependent,Exposure to the headerCan be

  • 8. Use Cocoapods to manage third-party dependencies

So let’s say we need to be inLjComponentA encapsulates network layer code, need to useThree party libraries AlamofireMake the following changes in your podfilethenpod installAfter success can be inLjComponentA uses the Alamofire librarytheAt this point, a local componentized module is configured

Cocoapods componentization

In addition to local componentization, you can also use Cocoapods, which works as shown belowAgain, take local componentization services as an example

Create a private repository

  • 1. Create a TestPodsComponent repository on Github

To do this, go to Github and click “+” in the upper right corner. Select New Repository. Enter Repository name as TestPodsComponent, select repository type as private, and click Create Repository.

  • 2. Add the private repository to the local ~/.cocoapods/repos directory
pod repo add TestPodsComponent https://github.com/xxxx/TestPodsComponent.git
Copy the code

Create the PODS project, or componentized project

  • 1. Create a vm using a terminalTestPodsComponentThe module
pod lib create TestPodsComponent
Copy the code
  • 2. Select a value as promptedIOS, Swift, Yes, None, No

  • 3. Go to the module directory and will need the filescopytoTestPodsComponent -> ClassesIn the

  • 4. Performpod install, updates the Classes content to pods

Configure PODS project

Modify the configuration files of the modules, namely TestPodsComponent podspec

  • To rely on third-party libraries, you need to configure S. dependency
S.dependency 'AFNetworking' # rely on AFNetworkingCopy the code
  • If modules need to reference each other, s.dependency must also be configured. For example, LjBase must reference LjService
//********1, modify podspec file pod 'LjServices' //********2, modify podfile pod 'LjServices' :path => '.. /.. /LjServices'Copy the code
  • If you need to load resources, such as images, JSON, bundles, etc
    • 1. Add the resource file to the Assets folder of the module
    • 2. Configure resource paths in the specs (mandatory!! Otherwise the resource cannot be read.
    • 3. Specify the path of the resource file
//*****1. Modify podspec s.lesource_bundles = {'LjBase' => ['LjBase/Assets/*']} //***** String = Bundle.init(for: dynamicClass.self).resourcePath! + "/LjBase.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

Submitted to git

The TestPodsComponent is a private library we have just built in Git: TestPodsComponent

  • Run the following terminal command

[Note] : After executing git add., you’d better run git status to check the status

Verify the PodSpec file

Run the terminal command pod spec lint

  • pod specRelative to thepod libwillmoreforaccurate
  • pod libThe equivalent of onlyvalidationaLocal repository
  • pod specwillAlso validate the local repositoryandRemote warehouse

Add —-allow-warnings to remove warnings

[if there is an ERROR: – ERROR | (iOS) file patterns: The “source_files” pattern did not match any file.”

This is because the corresponding folder is not found in CocoapOS. You can do the following

  • Go to/Users/username/Library/Caches/CocoaPods/Pods/External/your project name

  • Go to the latest log file and place it in the same path as the source_files file

Commit to a private repository

Execute the following command: pod repo push [local Spec repo name][Podspec file path]Once submitted successfully, the following is ready to use

use

  • To create a new project, add the following to the new project’s podfile:

  • Perform pod install

Now that we’ve componentized Cocoapods, we’ll look at communication between componentization in the next article

Related articles recommended links

IOS componentization – Basics

expand

The above we can see TestPodsComponent. Podspec content: s.n ame, s.v ersion let’s explain each item is what mean

  • s.name = “TestPodsComponent” The project name
  • s.version= “0.1.0 from”The version number corresponds to the label number in your warehouse
  • s.summary = ‘ this is a Test Pods Component.’ Project introduction
  • s.license = { :type => “MIT”, :file => “LICENSE” } Open Source License
  • s.homepage=”git.com/xxx” Warehouse home page
  • s.source      = { :git => “git.com/xxx.git”, :branch => ‘master’, :tag => “#{s.version}” } Your warehouse address, not your SSH address
  • s.source_files = “TestPodsComponent/Classes/. {h, m} or TestPodsComponent/Classes /Location of code
  • s.requires_arc = true Whether to enable ARC
  • s.platform= : ios, “9.0”Platform and the lowest supported version
  • s.xcconfig = { ‘OTHER_LDFLAGS’ => ‘-Objc -all_load -fobjc-arc’ ,’ENABLE_BITCODE’  => ‘NO’} Target related Settings
  • s.author = { “author” => “xxx.com” } Author information, open source online may be sent by email
  • s.frameworks = “UIKit”, “Foundation” Supported frameworks
  • s.resource_bundles = {‘TestPodsComponent’ => [‘TestPodsComponent/Assets/*.png’]} Resource file
  • s.dependency = “AFNetworking” Dependency libraries, write as many dependency libraries as possible
  • s.dependency‘AFNetworking’, ‘~ > 4.0’You can specify the version