• As companies continue to grow, the volume of application code will become larger, the business code will become more coupled, and the amount of code will increase dramatically
  • The separation of code alone is not enough to solve the code coupling between businesses, but componentization is a technique that can solve the code coupling and enable business engineering to run independently
  • This article covers the creation and management of remote private libraries and the use of local index libraries, as well as the guidance for publishing open source frameworks into CocoaPods
  • IOS componentized private library

Local library scheme

Create a local private library

  • First, you need a host projectMainMoudleAnd a folder for all local private librariesAllMoudlesThe two folders are in the same directory
  • inAllMoudlesCreate a private library in the folderTitanFMBase, created in a subdirectoryClassesFor storing all files, the directory is as follows:AllMoudles/TitanFMBase/Classes
  • inClassesAdd files to folders and submit them locallygit
/ / enter TitanFMBase folder/AllMoudles/CD XXX TitanFMBase / / initializes the git git init / / local code submitted to the local repository git add. / / changes to local warehouse git commit -m 'Your modification record' // Create a spec file pod Spec cTEate TitanFMBaseCopy the code

Finally, open TitanFMBase. Podspec in the TitanFMBase folder and modify the corresponding configuration information. See Modify Blog

Pay attention to the point

The Git address for the local library is not required in the Source configuration

s.source = { :git => "", :tag => "#{s.version}" }
Copy the code

Use local private libraries

  • Installing and using a local private library is the same as using a remote private library, except that:
    • Remote private libraries do not need to specify the address of the library
    • Local private libraries need to specify the library address (relative path only)
  • usepathAdd framework dependencies in the form of
pod 'TitanFMBase', :path => '.. /AllMoudles/TitanFMBase'
Copy the code

Pay attention to the point

  • Join the local private library, do not need to usepod lib lintorpod spec lintvalidationspecCorrectness of files
  • Because some fields need to be set only in remote private libraries, as long as the path of the local private library is correct, it does not affect the use

Remote private library

  • When we execute at the terminalpod searchCommand, the search is actually locally cachedspecThe file, of course, needs to be updated locally for the first timespecfile
  • It can be executed on the terminalpod repoCommand to view the current local index library, or view the directory~/.cocoapods/repos/master/Specs
  • In componentized development, to prevent code leakage, we must create our own local index library
  • Publish the open source framework into CocoaPods pit guideOne way to do this is mentioned in the article
    • However, you need to manually create the vmpodspecfile
    • You need to manually manage Git instead of testing. You need to manually add a test project
  • performpod repo add TitanSpec http://xxxxCommand to create a new local index library
  • Create remote index library, code market
  • Except for the red arrow in the figure, you do not need to fill in other parts. You can create a new one

Create a remote private library

  • pod lib create xxx
  • Specification to create a private library, execute the command above, can be created at the same timespecDocumentation and test engineering, etc
  • Create a different configuration file as prompted, and then place the private library file to be addedxxx/xxx/ClassesThe default. M file can be deleted
  • And then you have to open it upExampleDirectory under the test project, and executepod installCommand to install your private library files into the test project
  • Last modifiedxxxUnder the filexxx.podspecThe related configuration in the file is sufficient

You can commit all the project files to a remote private repository

Git add. // Commit your changes to the local repository git commit -m 'your changes' // check the current remote connection git remote add. // Add the origin remote connection git remote add Origin 'your Github project address' // Before push, Pod lib lint // Pod spec lint // Push the code from the master branch to a remote repository named Origin origin masterCopy the code
  • In normal cases, local authentication usually works, while remote authentication normally has problems
  • Local authentication does not validates.sourceAt the back of thetag
  • Remote authentication verifiestagAnd so far ourtagIt hasn’t been set up yet, so the authentication won’t pass and you need to tag it
  • Set uptagAgain, it should be no problem
// Check the current tag value
git tag

// Set the tag value
git tag "0.0.1"  

// Upload the commit tag
git push --tags


// Delete tag related commands
// Delete the local label and then the remote label
// Delete the local label
git tag -d 0.01.

// Delete the remote label
git push origin :0.01.

Copy the code

Submit the private SpecRepo

Submit a PodSpec to a private SpecRepo:

pod repo push SpecName XXX.podspec
Copy the code

Pay attention to the point

  • submitpodspecThere is validation in the process, and it is best to validate before submittingspecThe configuration of the file is wrongpod lib lint
    • Warnings can be used--allow-waringsignore
    • But the error messages involved must be addressed
  • During the commit process, information is committed to a remote private index library

Using a private library

  • To retrieve private libraries:pod search XXX
    • If not, you can first go to the private index library to see if there is a private library
    • If it exists and cannot be retrieved, delete the private library index file and reconfigure it
  • inPodfileIn the file, colleagues using private libraries and third-party libraries need to specify the correspondingsourceThe source
  • pod repoResult after the command is executed
master
- Type: git (master)
- URL:  'https://github.com/CocoaPods/Specs.git'
- Path: /Users/xxx/.cocoapods/repos/master

TitanFMSpec
- Type: git (master)
- URL:  'https://git.coding.net/CoderTitan/TitanFMSpec.git'
- Path: /Users/xxx/.cocoapods/repos/TitanFMSpec
Copy the code

Configuration information in the Podfile file

// Remote private librarysource 'https://git.coding.net/CoderTitan/TitanFMSpec.git'// The official warehousesource 'https://github.com/CocoaPods/Specs.git'

platform :ios, '8.0'

target 'TitanjunFM' do
  use_frameworks!

pod 'TitanFMBase'
pod 'MJExtension'

end
Copy the code

Updating a private library

Update remote private libraries

  1. Modify thexxx/xxx/ClassesFolder under the corresponding library file
  2. Update the test engineeringPodLibrary file:pod update --no-repo-update
  3. updatexxx.podspecThe configuration information and version number of the file must be changed
  4. Commit code to remote repository:git push origin master
  5. updatetagTags:git push --tags
  6. Update remote and local private index libraries:pod repo push SpecName XXX.podspec

Private library dependencies

Preliminary design scheme

  • When designing a private library, it is inevitable to use other third-party libraries, and how to solve this problem
  • Add component dependencies: inpodspecAdd the following dependency code to the file configuration
s.dependency 'AFNetworking'
s.dependency 'SDWebImage'
Copy the code
  • Pay attention to dependencies, as well as the framework header file, do not directly import the dependency framework header file
  • That is, the above mentioned dependencies on third-party libraries in the projectPodfileFile, the class library is no longer imported

Optimization scheme

The problem with the above scenario is that if another line of business relies only on some basic configuration, but if the entire library is used as a dependency, some redundant code is imported

  • So, we’re now doing terminal executionpod search AFNetworking, take a look atAFNetworkingSearch results for
  • You will seeSubspecs,AFNetworkingIt is divided into several different parts, so that we can import different parts of the code according to different functional requirements, to prevent code redundancy
-> AFNetworking (3.2.1) A delightful iOS and OS X Networking Framework.pod'AFNetworking'.'~ > 3.2.1'- Homepage: https://github.com/AFNetworking/AFNetworking - Source: https://github.com/AFNetworking/AFNetworking.git - Versions: 3.2.1,... ,0.5.1 [Master repo] - Subspecs: - AFNetworking/Serialization (3.2.1) - AFNetworking/Security (3.2.1) - AFNetworking/Reachability (3.2.1) AFNetworking/NSURLSession (3.2.1) - AFNetworking/UIKit (3.2.1)Copy the code

To solve the problem of dividing the code in the private library into different functional modules, configure the PodSpec file using the subspec syntax as follows:

// format: s.subspec'XXX' do| | x / / you need to import the relative paths of all files x.s ource_files ='Relative path /**/*'// Relative path of the. H header file to be imported x.public_header_files ='/**/*.h'// Relative path of the resource file to be imported x.resource =/**/*.{bundle,nib,xib}// Other libraries to rely on'AFNetworking'.'~ > 1.0.0'End // Example: s.subspec'Network' do |n|
    n.source_files = 'TitanFMBase/Classes/Network/**/*'
    n.dependency 'AFNetworking'
end
Copy the code
  • The originals.source_filesChange the above syntax
  • For external use, just importpod 'AFNetworking/Reachability'Can be

Resource references to private libraries

xib&storyboard

  • All private librariesxibMust be acquired dynamically
  • Private library reference image resources orXibHow do you refer to a resource?
  • You know the references in the projectXibWhen, the usual way is[[NSBundle mainBundle] load]However, this approach is obviously not applicable in private libraries
  • Load the private library in the private libraryXIb, method of use[NSBundle bundleForClass:self]Dynamic fetch, let’s see
// MiddleView.m NSBundle *mainBundle = [NSBundle mainBundle]; NSBundle *bundle = [NSBundle bundleForClass:self]; MiddleView *middleView = [[bundle loadNibNamed:@"MiddleView" owner:nil options:nil] firstObject]; // mainBundle: NSBundle </Users/xxx/Library/Developer/CoreSimulator/Devices/6B74958F-560F-4BF4-9BDF-9AD789379FC9/data/Containers/Bundle/Applicat ion/FC9747F0-8A82-4643-AC7E-BDC268190B8D/TitanFM.app> // bundle: NSBundle </Users/xxx/Library/Developer/CoreSimulator/Devices/6B74958F-560F-4BF4-9BDF-9AD789379FC9/data/Containers/Bundle/Applicat ion/FC9747F0-8A82-4643-AC7E-BDC268190B8D/TitanFM.app/Frameworks/TitanFMMain.framework>Copy the code
  • As you can see from the above information, the project is normalXibSuch resource files are placed inTitanFM.appIn the
  • Private libraryXibSuch resource files are placed inTitanFM.app/Frameworks/TitanFMMain.frameworkFile directory, so the resources in the private library file load, to the corresponding file directory
  • You can also go toTitanFM.appTo find the correspondingappFile, display package content, you can view hierarchy

Image resources

Picture storage problem

  • In normal projects, our images will be placed in similar suffixes.xcassetsIn the file
  • When designing a private library, theClassesOne is created by default in the sibling directory ofAssetsFor storing images and other resources
  • inpodspecIn the file, modify the configuration of loading file resources as follows:
s.resource_bundles = {
   'MainMoudle' => ['MainMoudle/Assets/*']
}
Copy the code

After modifying the configuration information and images, run pod Install to import the resource files into the project

Use of private library images

To load an image in a XIB, you need to prefix the image with the main bundle of the component, like mainmoudle. bundle/tabbat_back

Private libraries that use code to load images must not use the imageNamed method

1. Obtain the current bundleName
NSBundle *currentBundle = [NSBundle bundleForClass:[self class]].//2. Retrieve the image path in the bundle based on the image name
NSString *path = [currentBundle pathForResource:@"[email protected]" ofType:nil inDirectory:@"MainMoudle.bundle"];

// Get the image
UIImage *image = [UIImage imageWithContentsOfFile:path];
Copy the code

One thing to note about using pictures is this

  • Image references are not automatically selected@ 2 x and @ 3 xSo you must manually specify the specific picture name including the picture suffix
  • A method to get a pathpathForResourceYou must also specify where the picture is locatedbundlePath, that is,inDirectoryThe parameter cannot be empty

Submit the local private library index

  • When your private library references other private library frameworks, for exampleMainMoudleReferenced in theTitanFMBase/CategoryPart of the
  • Remember not to do local and remotespecVerify, otherwise it might return wrong, just becausespecThe default dependent library is the common index library. The private library cannot be retrieved. The following figure shows the error message
  • If you encounter a similar error during the local index submission process, you can ignore the commit directly, but other error messages, remember to modify, warning can be ignored, but cannot ignore the error message (except the problem of relying on private library).
// Submit the local private index library to ignore the warning command
pod repo push TitanjunSpec MainMoudle.podspec --allow-warnings
Copy the code

Relevant reference

  • IOS componentization reference article

Please scan the following wechat official account and subscribe to my blog!