background

As a sequel to my previous post on iOS componentization, I’ll talk about componentization implementation and integration on iOS using Cocoapods.

The results of

The two examples in this article can be found in the YTThirdPlatformManager project.

Tool is introduced

Cocoapods is a development library management tool for iOS/ OSX platforms. After simple configuration and installation commands are executed, Cocoapods automatically downloads third-party libraries and performs corresponding configuration, simplifying the process of introducing third-party libraries and making development easier and more efficient. It is a necessary tool for iOS development. Using Cocoapods as a componentized tool is a good choice.

Installation and Setup

Installation and design can be referred to this article: Cocopods Installation and Upgrade Memo

implementation

Simple project componentization

Componentization of a simple project with a test module decoupling scenario consists of the following

  • Pod library project creation
  • Explains the most basic podSpec file written
  • Client integration

Create a project

When creating a project using pod Lib Create, you will encounter several areas that require input. See the comments in the code snippet for details

➜ DevPods pod lib create PTTestKit Cloning ` https://github.com/CocoaPods/pod-template.git ` into ` PTTestKit `. You  PTTestKit template. ------------------------------ To get you started we need to ask a few questions, this should only take a minute. If this is your first time we recommend running through with the guide: - http://guides.cocoapods.org/making/using-pod-lib-create.html ( hold cmd and double click links to openin a browser. )

# The language used
What language do you want to use?? [ Swift / ObjC ]
 > Objc

Specify YES for modular decoupling tests
Would you like to include a demo application with your library? [ Yes / No ]
 > 
yes

No need to specify None for integrated test modules
Which testing frameworks will you use? [ Specta / Kiwi / None ]
 > None

# UI test module, No need to specify No
Would you like to do view based testing? [ Yes / No ]
 > No

# specify the class prefix
What is your class prefix?
 > PT

Running pod install on your new library.
Copy the code

Podspec file

A simple PodSpec file is shown below, and you can see the comments in the code for explanations of specific fields


Pod::Spec.new do |s|
  s.name             = 'PTTestKit'
  s.version          = '0.1.0 from'
  s.summary          = 'Wow PTTestKit.'

# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!

    # Long description
  s.description      = <<-DESC Wow this is a amazing kit, Enjoy yourself! DESC

    If you do not commit, you can specify any value, but you need to keep this item, otherwise you will get an error
    # attributes: Missing required attribute `homepage`.
    s.homepage         = 'https://github.com/flypigrmvb/PTTestKit'
    # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
    # License file
    s.license          = { :type= >'MIT'.:file= >'LICENSE' }
    # User information
    s.author           = { 'flypigrmvb'= >'[email protected]' }
    Git git git git git git git git git git git git git git
    # attributes: Missing required attribute `source`.
    s.source           = { :git= >'https://github.com/flypigrmvb/PTTestKit.git'.:tag => s.version.to_s }
    # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

    # specify the lowest ios version
    s.ios.deployment_target = '8.0'

    The path to the source file
    s.source_files = 'PTTestKit/Classes/**/*'

    Public header file, set as needed
    s.public_header_files = 'PTTestKit/Classes/Public/**/*.h'
    # Private header file, set as needed
    s.private_header_files = 'PTTestKit/Classes/Private/**/*.h'
    # Dependent system Framework, set as needed
    # s.frameworks = 'UIKit', 'MapKit'
    # Rely on other POD libraries, as needed
    # s.dependency 'AFNetworking', '~> 2.3'
end
Copy the code

Client integration

If you integrate the Example test project in the step of creating the Pod library project, the podfile under the test project contains the current Pod library project by default

#use_frameworks!

target 'PTTestKit_Example' do
  pod 'PTTestKit'.:path= >'.. / '

  target 'PTTestKit_Tests' do
    inherit! :search_paths

    
  end
end
Copy the code

Switch to the test project directory and run the pod install command. After that, the test project integrates with the POD project. Here is a simple example z of using some of the Pod library project features in your test project

#import "PTViewController.h"
#import <PTTestKit/PublicFile.h>
/ /!!!!! Private Headers can be imported
#import <PTTestKit/PrivateFile.h>
/ /!!!!! An error
//#import <PTTestKit/ProjectFile.h>

@interface PTViewController(a)

@end

@implementation PTViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self addActionWithName:@"Test" callback:^{
        NSLog(@ "= = = =");
    }];
    
    [self addActionWithName:@"PrivateFile" callback:^{
        [PrivateFile test];
    }];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [PrivateFile test];
}

@end
Copy the code

Modular componentization

Take a third-generation component integration scenario as an example to realize modular componentization, which mainly includes the following contents:

  • Create core modules
  • Creating submodules
  • Client integration

The process of creating a POD library project is the same as the simple module component steps, which will not be described here

Podspec file

This file creates a Core module that houses abstract interfaces, base classes, and some common utility classes and header files, as well as several submodules for specific third-party platform implementations. For details, see the comments in the code below


Pod::Spec.new do |s|
  s.name             = 'PTThirdPlatformKit'
  s.version          = '0.1.0 from'
  s.summary          = 'A short description of PTThirdPlatformKit.'

# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!

  s.description      = <<-DESC TODO: Add long description of the pod here. DESC

    s.homepage         = 'https://github.com/flypigrmvb/PTThirdPlatformKit'
    # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
    s.license          = { :type= >'MIT'.:file= >'LICENSE' }
    s.author           = { 'flypigrmvb'= >'[email protected]' }
    s.source           = { :git= >'https://github.com/flypigrmvb/PTThirdPlatformKit.git'.:tag => s.version.to_s }
    # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

    s.ios.deployment_target = '8.0'
    If the pod project in the POD file does not specify a submodule, import the module specified here
    s.default_subspec = 'Core'

    Define a core module where users hold abstract interfaces, base classes, and some common utility classes and header files
    s.subspec 'Core' do |subspec|
        # source code
        subspec.source_files = 'PTThirdPlatformKit/Classes/**/*'
        Configure the system Framework
        subspec.frameworks = 'CoreMotion'
        subspec.dependency 'SDWebImage'
        Add a dependent system static library
        subspec.libraries = 'xml2'.'z'.'c++'.'stdc++.6'.'sqlite3'
    end


    # Alipay module
    s.subspec 'AlipayManager' do |subspec|
        # source code
        subspec.source_files = 'PTThirdPlatformKit/AlipayManager/**/*'
        Add resource file
        subspec.resource = 'PTThirdPlatformKit/AlipayManager/**/*.bundle'
        # Add a framework that relies on third parties
        subspec.vendored_frameworks = 'PTThirdPlatformKit/AlipayManager/**/*.framework'
        Add a framework that depends on the system
        subspec.frameworks = 'CoreTelephony'.'SystemConfiguration'
        # Dependency core modules
        subspec.dependency 'PTThirdPlatformKit/Core'
    end


    Module # QQ
    s.subspec 'TencentManager' do |subspec|
        # source code
        subspec.source_files = 'PTThirdPlatformKit/TencentManager/**/*'
        Add resource file
        subspec.resource = 'PTThirdPlatformKit/TencentManager/**/*.bundle'
        # Add a framework that relies on third parties
        subspec.vendored_frameworks = 'PTThirdPlatformKit/TencentManager/**/*.framework'
        Add a framework that depends on the system
        subspec.frameworks = 'SystemConfiguration'
        # Dependency core modules
        subspec.dependency 'PTThirdPlatformKit/Core'
    end


    # Microblog module
    s.subspec 'WeiboManager' do |subspec|
        # source code
        subspec.source_files = 'PTThirdPlatformKit/WeiboManager/**/*'
        # Rely on the Pod library of microblogging
        subspec.dependency 'WeiboSDK'
        subspec.dependency 'PTThirdPlatformKit/Core'
    end


    # wechat module
    s.subspec 'WXManager' do |subspec|
        # source code
        subspec.source_files = 'PTThirdPlatformKit/WXManager/**/*'
        # Rely on wechat POD library
        subspec.dependency 'WechatOpenSDK'
        subspec.dependency 'PTThirdPlatformKit/Core'
    end

end
Copy the code

Client integration

The podfile file is shown below and you can import the main module and any combination of submodules

#use_frameworks!
platform :ios.'8.0'

target 'PTThirdPlatformKit_Example' do

    pod 'PTTestKit'.:path= >'.. /.. /PTTestKit'

    # main module
    pod 'PTThirdPlatformKit'.:path= >'.. / '
    # Submodules are fast
    pod 'PTThirdPlatformKit/AlipayManager'.:path= >'.. / '
    pod 'PTThirdPlatformKit/TencentManager'.:path= >'.. / '
    pod 'PTThirdPlatformKit/WeiboManager'.:path= >'.. / '
    pod 'PTThirdPlatformKit/WXManager'.:path= >'.. / '
  
end

target 'PTThirdPlatformKit_Example_Developer' do
    pod 'PTTestKit'.:path= >'.. /.. /PTTestKit'
    
    pod 'PTThirdPlatformKit'.:path= >'.. / '
    pod 'PTThirdPlatformKit/AlipayManager'.:path= >'.. / '
    pod 'PTThirdPlatformKit/TencentManager'.:path= >'.. / '
    pod 'PTThirdPlatformKit/WeiboManager'.:path= >'.. / '
    pod 'PTThirdPlatformKit/WXManager'.:path= >'.. / '
    
end
Copy the code

Have a problem

The Pod library under development depends on the processing of another Pod library

Reference: guides.cocoapods.org/syntax/pods… Podspec file to add

s.vendored_frameworks = 'PTDataModule/Frameworks/*.framework'
Copy the code

Configure non-ARC files in the ARC environment

Need to use podspec subspec and requires_arc reference in the rule: guides.cocoapods.org/syntax/pods… Guides.cocoapods.org/syntax/pods…

s.requires_arc = true

        # no arc files rules
        non_arc_files = 'PTDataModule/Classes/**/JSONKit.{h,m}'
        s.exclude_files = non_arc_files
        s.subspec 'no-arc' do |sna|
            sna.requires_arc = false
            sna.source_files = non_arc_files
        end
Copy the code

PrefixHeader

Reference: guides.cocoapods.org/syntax/pods…

Podspec specifies the PTDataModule-prefixheader. PCH file

s.prefix_header_file = 'PTDataModule/SupportFiles/PTDataModule-prefixheader.pch'
Copy the code

PTDataModule- prefixHeader. PCH file contents

#import "UtilMacro.h"
#import "DebugConfig.h"
#import "TIMAdapter.h"
Copy the code

There is a bug where the custom PCH file is not found in the project after using Pod Install, but the content is added to PTDataModule- prefix-pch file

Can use this way, the need to import directly to the header files using parameters specified reference: guides.cocoapods.org/syntax/pods…

spec.prefix_header_contents = '#import <UIKit/UIKit.h>'.'#import <Foundation/Foundation.h>'
Copy the code

Pod update failure

[!]  The'Pods-PTThirdPlatformKit_Example'target has transitive dependencies that include static binaries: (/ Users/aron/PuTaoWorkSpace/Plush_devpods_developer/DevPods/PTThirdPlatformKit/Example/Pods/WechatOpenSDK/OpenSDK1.8.0 / l ibWeChatSDK.a and /Users/aron/PuTaoWorkSpace/Plush_devpods_developer/DevPods/PTThirdPlatformKit/Example/Pods/WeiboSDK/libWeiboSDK/libWeibo SDK.a)Copy the code

#use_frameworks! (Note this)

Add. A static library and the corresponding header PTBehaviorStat

s.public_header_files = 'PTBehaviorStat/Classes/**/*.h'.'PTBehaviorStat/vendor/**/*.h'
s.vendored_library = 'PTBehaviorStat/**/*.a'
Copy the code

Pod lib create problem with GitHub template data

The –template argument specifies the local template data

The Pod development library relies on the local development library

Reference: stackoverflow.com/questions/1… For example, Pod development library A depends on Pod development library B. The dependency information is as follows. You do not need to specify A path to obtain other information

s.dependency 'DevLibB'
Copy the code

Import DevLibB in the podfile of the test project or client project that needs to be displayed

pod 'DevLibB'.:path= >'.. /.. /DevLibB'
Copy the code

Source files cannot be found without configuration pairs

subspec.source_files = 'PTThirdPlatformKit/WeiboManager/**/*'
Copy the code

If the configuration (as shown below) is the wrong path, the class will not be found on the client side, and you need to check that the source file is configured correctly

subspec.source_files = 'PTThirdPlatformKit/WeiboManager111/**/*'
Copy the code

conclusion

The above is a summary of my componentized integration practice using Cocoapods and some of the problems I encountered. I hope it will be helpful to those who need it.

Refer to the link

Cocoapods project home page