IOS package dependency management tools

IOS package dependency management tool (part 1) : CocoaPods

IOS package dependency management tool (ii) : CocoaPods principle and knowledge

IOS package dependency management tool (3) : create your own Pod library

IOS Package dependency Management tool (4) : Swift Package Manager (SPM) Introduction

IOS Package dependency Management tool (5) : Swift Package Manager (SPM) Customization

IOS package dependency management tools (6) : CocoaPods VS SPM Summary

One, foreword

In the previous article, we saw how SPM helps us access third-party dependencies quickly. In reality, not only do we need to rely on third-party sources, but we often need to make projects modular and componentized; Like CocoaPods, we need to customize the library and have our projects rely on it; This article will briefly analyze the composition of the SPM library and create our own SPM library.

2. SPM library composition

2.1. Directory Structure

Let’s first analyze the directory structure of “Alamofire”, as shown below:

In the figure above, the red boxes indicate the most basic components of the SPM library:

  • Package.swift: This file is the Package description file, which is in the right-hand edit area, but there is more to it than that;
  • Source directory: the directory where the package’s Source files are located;

2.2 Composition analysis of Package.swift

Package.swift is the entire Package description, which relies on the PackageDescription structure, which defines what configuration information an SPM export Package needs to specify:

// struct Package
init(
    name: String, 
    defaultLocalization: LanguageTag? = nil, 
    platforms: [SupportedPlatform]? = nil, 
    pkgConfig: String? = nil, 
    providers: [SystemPackageProvider]? = nil, 
    products: [Product] = [], 
    dependencies: [Package.Dependency] = [], 
    targets: [Target] = [], 
    swiftLanguageVersions: [SwiftVersion]? = nil, 
    cLanguageStandard: CLanguageStandard? = nil, 
    cxxLanguageStandard: CXXLanguageStandard? = nil
)
Copy the code
  • Name: Swift package name.
  • DefaultLocalization: the defaultLocalization of the resource;
  • Platforms: A list of the lowest supported system platforms;
  • PkgConfig: Name used for the C module. If so, Xcode will search the.PC file for additional flags needed for the system target;
  • Providers: package providers of system goals;
  • Products: List of products available to customers by this package;
  • Dependencies: List of software package dependencies (which can be empty or require other external dependencies)
  • Targets: lists the targets (source directory, test directory) that belong to this package.
  • SwiftLanguageVersions: list of compatible Swift versions for this package;
  • CLanguageStandard: THE C language standard for all C targets in this package;
  • CxxLanguageStandard: the C ++ language standard for all C ++ targets in this package;

In general, with these configurations, we need: name, Platforms, products, dependencies, targets.

3. Create your own SPM library

3.1 Two ways to create an SPM library

Method 1 (Xcode instrumented) create:

Enter a project name and click “Create” :

Xcode automatically generates configuration files and source directories for us:

Method 2 (CLI) Create:

$mkdir DemoLogger && CD DemoLogger $swift package init DemoLogger Creating Package.swift Creating README.md Creating .gitignore Creating Sources/ Creating Sources/DemoLogger/DemoLogger.swift Creating Tests/ Creating Tests/LinuxMain.swift Creating Tests/DemoLoggerTests/ Creating Tests/DemoLoggerTests/DemoLoggerTests.swift Creating Tests/DemoLoggerTests/XCTestManifests.swiftCopy the code

3.2. Write our SPM library

  • Logger.swift code is as follows (emphasis: constructor!! \color{red}{key: constructor!! } key: constructor!! :
public struct Logger { var DEBUG: Bool = false // this is a struct, so it is possible not to write init. // However, because it is encapsulated in SPM library, it needs to be exposed. Public init() {} public init(_ DEBUG: Bool) {self.debug = DEBUG} public func log(_ MSG: Bool) {self.debug = DEBUG} public func log(_ MSG: String) { if DEBUG { print("Logger\t\(msg)") } } }Copy the code
  • Modify the test case, otherwise an error will be reported:
import XCTest
@testable import Logger

final class LoggerTests: XCTestCase {
    func testExample() {
        Logger(true).log("chris.yang")
    }

    static var allTests = [
        ("testExample", testExample),
    ]
}
Copy the code

Then “Command + B” compiles successfully!

3.3. Locally integrate SPM library

Our custom SPM library cannot be submitted to Git every time it is modified. It must be integrated locally, tested logic, and finally stabilized before submitting to Git. However, if you go to add through SPM, you can only enter git URL. Can’t add local SPM library, what can I do?

The method is as follows:

  1. Shut down our SPM Xcode project (absolutely!!) ;
  2. Open our project project;
  3. Drag our custom SPM directly into the project as shown below:

After dragging in, the picture is as follows:

  1. Add framework link as shown below:

Click “+” and choose the following:

Click “Add” :

  1. Introduce the custom library and test it as shown below:

OK! Perfect, uncompromising…. Next, we can consider uploading to Git cloud.

3.4. Upload to Github

  • Create Git repository:

You are advised to select README,. Gitignore, and License, and then click Create Repository.

  • Clone && Commit (tag recommended) :

3.5. Reintegrate

  • Remove the SPM library in “Frameworks”

  • Example Remove the local SPM Reference

Add the source according to the previous Swift Package Manager (SPM) Introduction:

Finally, a complete family photo: