跳到主內容

Swift Package Manager 外掛作者指南

如何為 iOS 和 macOS 外掛新增 Swift Package Manager 相容性

Flutter 的 Swift Package Manager 整合具有多種優勢

  1. 提供對 Swift 包生態系統的訪問。Flutter 外掛可以使用不斷增長的 Swift 包 生態系統!
  2. 簡化 Flutter 安裝。Swift Package Manager 與 Xcode 捆綁在一起。將來,您無需安裝 Ruby 和 CocoaPods 即可定位 iOS 或 macOS。

如何啟用 Swift Package Manager

#

Flutter 的 Swift Package Manager 支援預設情況下是關閉的。要啟用它

  1. 升級到最新的 Flutter SDK

    sh
    flutter upgrade
    
  2. 啟用 Swift Package Manager 功能

    sh
    flutter config --enable-swift-package-manager
    

使用 Flutter CLI 執行應用 遷移專案 以新增 Swift Package Manager 整合。這將使您的專案下載 Flutter 外掛所依賴的 Swift 包。使用 Swift Package Manager 整合的應用需要 Flutter 版本 3.24 或更高版本。要使用舊版本的 Flutter,您需要 刪除 Swift Package Manager 整合

對於尚未支援 Swift Package Manager 的依賴項,Flutter 將回退到 CocoaPods。

如何停用 Swift Package Manager

#

停用 Swift Package Manager 將導致 Flutter 為所有依賴項使用 CocoaPods。但是,Swift Package Manager 仍然整合到您的專案中。要完全從專案中刪除 Swift Package Manager 整合,請按照 如何刪除 Swift Package Manager 整合 說明進行操作。

為單個專案停用

#

在專案的 pubspec.yaml 檔案中,在 flutter 部分下,在 config 子部分中將 enable-swift-package-manager 設定為 false

pubspec.yaml
yaml
# The following section is specific to Flutter packages.
flutter:
  config:
    enable-swift-package-manager: false

這會為該專案的所有貢獻者停用 Swift Package Manager。

為所有專案全域性停用

#

執行以下命令

sh
flutter config --no-enable-swift-package-manager

這會為當前使用者停用 Swift Package Manager。

如果專案與 Swift Package Manager 不相容,所有貢獻者都需要執行此命令。

如何將 Swift Package Manager 支援新增到現有的 Flutter 外掛

#

本指南介紹瞭如何將 Swift Package Manager 支援新增到已經支援 CocoaPods 的外掛。這可確保外掛可供所有 Flutter 專案使用。

在進一步通知之前,Flutter 外掛應同時支援 Swift Package Manager 和 CocoaPods。

Swift Package Manager 的採用將是漸進的。不支援 CocoaPods 的外掛將無法被尚未遷移到 Swift Package Manager 的專案使用。不支援 Swift Package Manager 的外掛可能會給已遷移的專案帶來問題。

在整個指南中,將 plugin_name 替換為您的外掛名稱。下面的示例使用 ios,請根據需要將 ios 替換為 macos/darwin

  1. 啟用 Swift Package Manager 功能.

  2. 首先在 iosmacos 和/或 darwin 目錄中建立一個目錄。將此新目錄命名為平臺包的名稱。

    • plugin_name/
      • ios/
        • plugin_name/
  3. 在此新目錄中,建立以下檔案/目錄

    • Package.swift (檔案)
    • Sources (目錄)
    • Sources/plugin_name (目錄)

    您的外掛應如下所示

    • plugin_name/
      • ios/
        • plugin_name/
          • Package.swift
          • Sources/
            • plugin_name/
  4. Package.swift 檔案中使用以下模板

    Package.swift
    swift
    // swift-tools-version: 5.9
    // The swift-tools-version declares the minimum version of Swift required to build this package.
    
    import PackageDescription
    
    let package = Package(
        // TODO: Update your plugin name.
        name: "plugin_name",
        platforms: [
            // TODO: Update the platforms your plugin supports.
            // If your plugin only supports iOS, remove `.macOS(...)`.
            // If your plugin only supports macOS, remove `.iOS(...)`.
            .iOS("13.0"),
            .macOS("10.15")
        ],
        products: [
            // TODO: Update your library and target names.
            // If the plugin name contains "_", replace with "-" for the library name.
            .library(name: "plugin-name", targets: ["plugin_name"])
        ],
        dependencies: [],
        targets: [
            .target(
                // TODO: Update your target name.
                name: "plugin_name",
                dependencies: [],
                resources: [
                    // TODO: If your plugin requires a privacy manifest
                    // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file
                    // to describe your plugin's privacy impact, and then uncomment this line.
                    // For more information, see:
                    // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
                    // .process("PrivacyInfo.xcprivacy"),
    
                    // TODO: If you have other resources that need to be bundled with your plugin, refer to
                    // the following instructions to add them:
                    // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package
                ]
            )
        ]
    )
    
  5. 更新 Package.swift 檔案中的 支援的平臺

    Package.swift
    swift
        platforms: [
            // TODO: Update the platforms your plugin supports.
            // If your plugin only supports iOS, remove `.macOS(...)`.
            // If your plugin only supports macOS, remove `.iOS(...)`.
            .iOS("13.0"),
            .macOS("10.15")
        ],
    
  6. 更新 Package.swift 檔案中的包、庫和目標名稱。

    Package.swift
    swift
    let package = Package(
        // TODO: Update your plugin name.
        name: "plugin_name",
        platforms: [
            .iOS("13.0"),
            .macOS("10.15")
        ],
        products: [
            // TODO: Update your library and target names.
            // If the plugin name contains "_", replace with "-" for the library name
            .library(name: "plugin-name", targets: ["plugin_name"])
        ],
        dependencies: [],
        targets: [
            .target(
                // TODO: Update your target name.
                name: "plugin_name",
                dependencies: [],
                resources: [
                    // TODO: If your plugin requires a privacy manifest
                    // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file
                    // to describe your plugin's privacy impact, and then uncomment this line.
                    // For more information, see:
                    // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
                    // .process("PrivacyInfo.xcprivacy"),
    
                    // TODO: If you have other resources that need to be bundled with your plugin, refer to
                    // the following instructions to add them:
                    // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package
                ]
            )
        ]
    )
    
  7. 如果您的外掛具有 PrivacyInfo.xcprivacy 檔案,請將其移動到 ios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy 並取消註釋 Package.swift 檔案中的資源。

    Package.swift
    swift
                resources: [
                    // TODO: If your plugin requires a privacy manifest
                    // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file
                    // to describe your plugin's privacy impact, and then uncomment this line.
                    // For more information, see:
                    // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
                    .process("PrivacyInfo.xcprivacy"),
    
                    // TODO: If you have other resources that need to be bundled with your plugin, refer to
                    // the following instructions to add them:
                    // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package
                ],
    
  8. 將任何資原始檔從 ios/Assets 移動到 ios/plugin_name/Sources/plugin_name(或子目錄)。如果適用,將資原始檔新增到您的 Package.swift 檔案中。有關更多說明,請參閱 https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package

  9. 將所有檔案從 ios/Classes 移動到 ios/plugin_name/Sources/plugin_name

  10. ios/Assetsios/Resourcesios/Classes 目錄現在應該為空,並且可以刪除。

  11. 如果您的外掛使用 Pigeon,請更新您的 Pigeon 輸入檔案。

    pigeons/messages.dart
    dart
    kotlinOptions: KotlinOptions(),
    javaOut: 'android/app/src/main/java/io/flutter/plugins/Messages.java',
    javaOptions: JavaOptions(),
    swiftOut: 'ios/Classes/messages.g.swift',
    swiftOut: 'ios/plugin_name/Sources/plugin_name/messages.g.swift',
    swiftOptions: SwiftOptions(),
    
  12. 使用您可能需要的任何自定義更新您的 Package.swift 檔案。

    1. 在 Xcode 中開啟 ios/plugin_name/ 目錄。

    2. 在 Xcode 中,開啟您的 Package.swift 檔案。驗證 Xcode 是否未對此檔案產生任何警告或錯誤。

    3. 如果您的 ios/plugin_name.podspec 檔案具有 CocoaPods dependency,請將相應的 Swift Package Manager 依賴項新增到您的 Package.swift 檔案中。

    4. 如果您的包必須顯式連結 staticdynamic不推薦由 Apple 使用),請更新 Product 以定義型別

      Package.swift
      swift
      products: [
          .library(name: "plugin-name", type: .static, targets: ["plugin_name"])
      ],
      
    5. 進行任何其他自定義。有關如何編寫 Package.swift 檔案的更多資訊,請參閱 https://developer.apple.com/documentation/packagedescription

  13. 更新您的 ios/plugin_name.podspec 以指向新的路徑。

    ios/plugin_name.podspec
    ruby
    s.source_files = 'Classes/**/*.swift'
    s.resource_bundles = {'plugin_name_privacy' => ['Resources/PrivacyInfo.xcprivacy']}
    s.source_files = 'plugin_name/Sources/plugin_name/**/*.swift'
    s.resource_bundles = {'plugin_name_privacy' => ['plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy']}
    
  14. 更新從 bundle 載入資源以使用 Bundle.module

    swift
    #if SWIFT_PACKAGE
         let settingsURL = Bundle.module.url(forResource: "image", withExtension: "jpg")
    #else
         let settingsURL = Bundle(for: Self.self).url(forResource: "image", withExtension: "jpg")
    #endif
    
  15. 如果您的 .gitignore 不包含 .build/.swiftpm/ 目錄,您需要更新您的 .gitignore 以包含

    .gitignore
    .build/
    .swiftpm/
    

    提交您的外掛更改到您的版本控制系統。

  16. 驗證外掛是否仍然適用於 CocoaPods。

    1. 停用 Swift Package Manager。

      sh
      flutter config --no-enable-swift-package-manager
      
    2. 導航到外掛的示例應用。

      sh
      cd path/to/plugin/example/
      
    3. 確保外掛的示例應用可以構建和執行。

      sh
      flutter run
      
    4. 導航到外掛的頂級目錄。

      sh
      cd path/to/plugin/
      
    5. 執行 CocoaPods 驗證 lint。

      sh
      pod lib lint ios/plugin_name.podspec  --configuration=Debug --skip-tests --use-modular-headers --use-libraries
      
      sh
      pod lib lint ios/plugin_name.podspec  --configuration=Debug --skip-tests --use-modular-headers
      
  17. 驗證外掛是否適用於 Swift Package Manager。

    1. 啟用 Swift Package Manager。

      sh
      flutter config --enable-swift-package-manager
      
    2. 導航到外掛的示例應用。

      sh
      cd path/to/plugin/example/
      
    3. 確保外掛的示例應用可以構建和執行。

      sh
      flutter run
      
    4. 在 Xcode 中開啟外掛的示例應用。確保左側 專案導航器 中顯示 包依賴項

  18. 驗證測試是否透過。

在整個指南中,將 plugin_name 替換為您的外掛名稱。下面的示例使用 ios,請根據需要將 ios 替換為 macos/darwin

  1. 啟用 Swift Package Manager 功能.

  2. 首先在 iosmacos 和/或 darwin 目錄中建立一個目錄。將此新目錄命名為平臺包的名稱。

    • plugin_name/
      • ios/
        • plugin_name/
  3. 在此新目錄中,建立以下檔案/目錄

    • Package.swift (檔案)
    • Sources (目錄)
    • Sources/plugin_name (目錄)
    • Sources/plugin_name/include (目錄)
    • Sources/plugin_name/include/plugin_name (目錄)
    • Sources/plugin_name/include/plugin_name/.gitkeep (檔案)
      • 此檔案可確保提交該目錄。如果向該目錄添加了其他檔案,您可以刪除 .gitkeep 檔案。

    您的外掛應如下所示

    • plugin_name/
      • ios/
        • plugin_name/
          • Package.swift
          • Sources/plugin_name/include/plugin_name/
            • .gitkeep/
  4. Package.swift 檔案中使用以下模板

    Package.swift
    swift
    // swift-tools-version: 5.9
    // The swift-tools-version declares the minimum version of Swift required to build this package.
    
    import PackageDescription
    
    let package = Package(
        // TODO: Update your plugin name.
        name: "plugin_name",
        platforms: [
            // TODO: Update the platforms your plugin supports.
            // If your plugin only supports iOS, remove `.macOS(...)`.
            // If your plugin only supports macOS, remove `.iOS(...)`.
            .iOS("13.0"),
            .macOS("10.15")
        ],
        products: [
            // TODO: Update your library and target names.
            // If the plugin name contains "_", replace with "-" for the library name
            .library(name: "plugin-name", targets: ["plugin_name"])
        ],
        dependencies: [],
        targets: [
            .target(
                // TODO: Update your target name.
                name: "plugin_name",
                dependencies: [],
                resources: [
                    // TODO: If your plugin requires a privacy manifest
                    // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file
                    // to describe your plugin's privacy impact, and then uncomment this line.
                    // For more information, see:
                    // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
                    // .process("PrivacyInfo.xcprivacy"),
    
                    // TODO: If you have other resources that need to be bundled with your plugin, refer to
                    // the following instructions to add them:
                    // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package
                ],
                cSettings: [
                    // TODO: Update your plugin name.
                    .headerSearchPath("include/plugin_name")
                ]
            )
        ]
    )
    
  5. 更新 Package.swift 檔案中的 支援的平臺

    Package.swift
    swift
        platforms: [
            // TODO: Update the platforms your plugin supports.
            // If your plugin only supports iOS, remove `.macOS(...)`.
            // If your plugin only supports macOS, remove `.iOS(...)`.
            .iOS("13.0"),
            .macOS("10.15")
        ],
    
  6. 更新 Package.swift 檔案中的包、庫和目標名稱。

    Package.swift
    swift
    let package = Package(
        // TODO: Update your plugin name.
        name: "plugin_name",
        platforms: [
            .iOS("13.0"),
            .macOS("10.15")
        ],
        products: [
            // TODO: Update your library and target names.
            // If the plugin name contains "_", replace with "-" for the library name
            .library(name: "plugin-name", targets: ["plugin_name"])
        ],
        dependencies: [],
        targets: [
            .target(
                // TODO: Update your target name.
                name: "plugin_name",
                dependencies: [],
                resources: [
                    // TODO: If your plugin requires a privacy manifest
                    // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file
                    // to describe your plugin's privacy impact, and then uncomment this line.
                    // For more information, see:
                    // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
                    // .process("PrivacyInfo.xcprivacy"),
    
                    // TODO: If you have other resources that need to be bundled with your plugin, refer to
                    // the following instructions to add them:
                    // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package
                ],
                cSettings: [
                    // TODO: Update your plugin name.
                    .headerSearchPath("include/plugin_name")
                ]
            )
        ]
    )
    
  7. 如果您的外掛具有 PrivacyInfo.xcprivacy 檔案,請將其移動到 ios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy 並取消註釋 Package.swift 檔案中的資源。

    Package.swift
    swift
                resources: [
                    // TODO: If your plugin requires a privacy manifest
                    // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file
                    // to describe your plugin's privacy impact, and then uncomment this line.
                    // For more information, see:
                    // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
                    .process("PrivacyInfo.xcprivacy"),
    
                    // TODO: If you have other resources that need to be bundled with your plugin, refer to
                    // the following instructions to add them:
                    // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package
                ],
    
  8. 將任何資原始檔從 ios/Assets 移動到 ios/plugin_name/Sources/plugin_name(或子目錄)。如果適用,將資原始檔新增到您的 Package.swift 檔案中。有關更多說明,請參閱 https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package

  9. 將任何公共標頭檔案從 ios/Classes 移動到 ios/plugin_name/Sources/plugin_name/include/plugin_name

    • 如果您不確定哪些標頭檔案是公共的,請檢查您的 podspec 檔案中的 public_header_files 屬性。如果未指定此屬性,則所有標頭檔案都是公共的。您應該考慮是否希望所有標頭檔案都是公共的。

    • 在您的 pubspec.yaml 檔案中定義的 pluginClass 必須是公共的並且位於此目錄中。

  10. 處理 modulemap

    如果您的外掛沒有 modulemap,請跳過此步驟。

    如果您正在使用 modulemap 來建立 CocoaPods 的 Test 子模組,請考慮將其刪除以用於 Swift Package Manager。請注意,這將使所有公共標頭檔案透過模組可用。

    要刪除 Swift Package Manager 的 modulemap 但保留 CocoaPods 的 modulemap,請在外掛的 Package.swift 檔案中排除 modulemap 和 umbrella header。

    下面的示例假定 modulemap 和 umbrella header 位於 ios/plugin_name/Sources/plugin_name/include 目錄中。

    Package.swift
    swift
    .target(
        name: "plugin_name",
        dependencies: [],
        exclude: ["include/cocoapods_plugin_name.modulemap", "include/plugin_name-umbrella.h"],
    

    如果您希望您的單元測試與 CocoaPods 和 Swift Package Manager 相容,可以嘗試以下方法

    Tests/TestFile.m
    objc
    @import plugin_name;
    @import plugin_name.Test;
    #if __has_include(<plugin_name/plugin_name-umbrella.h>)
      @import plugin_name.Test;
    #endif
    

    如果您想為您的 Swift 包使用自定義 modulemap,請參閱 Swift Package Manager 的文件

  11. ios/Classes 中的所有剩餘檔案移動到 ios/plugin_name/Sources/plugin_name

  12. ios/Assetsios/Resourcesios/Classes 目錄現在應該為空,並且可以刪除。

  13. 如果您的標頭檔案不再與您的實現檔案位於同一目錄中,您應該更新您的匯入語句。

    例如,想象以下遷移

    • 之前

      ios/Classes/
      ├── PublicHeaderFile.h
      └── ImplementationFile.m
      
    • 之後

      ios/plugin_name/Sources/plugin_name/
      └── include/plugin_name/
         └── PublicHeaderFile.h
      └── ImplementationFile.m
      

    在此示例中,ImplementationFile.m 中的匯入語句應進行更新

    Sources/plugin_name/ImplementationFile.m
    objc
    #import "PublicHeaderFile.h"
    #import "./include/plugin_name/PublicHeaderFile.h"
    
  14. 如果您的外掛使用 Pigeon,請更新您的 Pigeon 輸入檔案。

    pigeons/messages.dart
    dart
    javaOptions: JavaOptions(),
    objcHeaderOut: 'ios/Classes/messages.g.h',
    objcSourceOut: 'ios/Classes/messages.g.m',
    objcHeaderOut: 'ios/plugin_name/Sources/plugin_name/messages.g.h',
    objcSourceOut: 'ios/plugin_name/Sources/plugin_name/messages.g.m',
    copyrightHeader: 'pigeons/copyright.txt',
    

    如果您的 objcHeaderOut 檔案不再與 objcSourceOut 位於同一目錄中,您可以使用 ObjcOptions.headerIncludePath 更改 #import

    pigeons/messages.dart
    dart
    javaOptions: JavaOptions(),
    objcHeaderOut: 'ios/Classes/messages.g.h',
    objcSourceOut: 'ios/Classes/messages.g.m',
    objcHeaderOut: 'ios/plugin_name/Sources/plugin_name/include/plugin_name/messages.g.h',
    objcSourceOut: 'ios/plugin_name/Sources/plugin_name/messages.g.m',
    objcOptions: ObjcOptions(
      headerIncludePath: './include/plugin_name/messages.g.h',
    ),
    copyrightHeader: 'pigeons/copyright.txt',
    

    執行 Pigeon 以使用最新的配置重新生成其程式碼。

  15. 使用您可能需要的任何自定義更新您的 Package.swift 檔案。

    1. 在 Xcode 中開啟 ios/plugin_name/ 目錄。

    2. 在 Xcode 中,開啟您的 Package.swift 檔案。驗證 Xcode 是否未對此檔案產生任何警告或錯誤。

    3. 如果您的 ios/plugin_name.podspec 檔案具有 CocoaPods dependency,請將相應的 Swift Package Manager 依賴項新增到您的 Package.swift 檔案中。

    4. 如果您的包必須顯式連結 staticdynamic不推薦由 Apple 使用),請更新 Product 以定義型別

      Package.swift
      swift
      products: [
          .library(name: "plugin-name", type: .static, targets: ["plugin_name"])
      ],
      
    5. 進行任何其他自定義。有關如何編寫 Package.swift 檔案的更多資訊,請參閱 https://developer.apple.com/documentation/packagedescription

  16. 更新您的 ios/plugin_name.podspec 以指向新的路徑。

    ios/plugin_name.podspec
    ruby
    s.source_files = 'Classes/**/*.{h,m}'
    s.public_header_files = 'Classes/**/*.h'
    s.module_map = 'Classes/cocoapods_plugin_name.modulemap'
    s.resource_bundles = {'plugin_name_privacy' => ['Resources/PrivacyInfo.xcprivacy']}
    s.source_files = 'plugin_name/Sources/plugin_name/**/*.{h,m}'
    s.public_header_files = 'plugin_name/Sources/plugin_name/include/**/*.h'
    s.module_map = 'plugin_name/Sources/plugin_name/include/cocoapods_plugin_name.modulemap'
    s.resource_bundles = {'plugin_name_privacy' => ['plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy']}
    
  17. 更新從 bundle 載入資源的方式,以使用 SWIFTPM_MODULE_BUNDLE

    objc
    #if SWIFT_PACKAGE
       NSBundle *bundle = SWIFTPM_MODULE_BUNDLE;
     #else
       NSBundle *bundle = [NSBundle bundleForClass:[self class]];
     #endif
     NSURL *imageURL = [bundle URLForResource:@"image" withExtension:@"jpg"];
    
  18. 如果您的 ios/plugin_name/Sources/plugin_name/include 目錄僅包含一個 .gitkeep 檔案,您需要更新您的 .gitignore 檔案以包含以下內容

    .gitignore
    !.gitkeep
    

    執行 flutter pub publish --dry-run 以確保 include 目錄已釋出。

  19. 提交您的外掛更改到您的版本控制系統。

  20. 驗證外掛是否仍然適用於 CocoaPods。

    1. 關閉 Swift Package Manager

      sh
      flutter config --no-enable-swift-package-manager
      
    2. 導航到外掛的示例應用。

      sh
      cd path/to/plugin/example/
      
    3. 確保外掛的示例應用可以構建和執行。

      sh
      flutter run
      
    4. 導航到外掛的頂級目錄。

      sh
      cd path/to/plugin/
      
    5. 執行 CocoaPods 驗證 lint

      sh
      pod lib lint ios/plugin_name.podspec  --configuration=Debug --skip-tests --use-modular-headers --use-libraries
      
      sh
      pod lib lint ios/plugin_name.podspec  --configuration=Debug --skip-tests --use-modular-headers
      
  21. 驗證外掛是否適用於 Swift Package Manager。

    1. 開啟 Swift Package Manager

      sh
      flutter config --enable-swift-package-manager
      
    2. 導航到外掛的示例應用。

      sh
      cd path/to/plugin/example/
      
    3. 確保外掛的示例應用可以構建和執行。

      sh
      flutter run
      
    4. 在 Xcode 中開啟外掛的示例應用。確保左側 專案導航器 中顯示 包依賴項

  22. 驗證測試是否透過。

如何更新外掛示例應用中的單元測試

#

如果您的外掛具有本地 XCTests,如果滿足以下條件之一,您可能需要更新它們以使其與 Swift Package Manager 協同工作

  • 您正在為測試使用 CocoaPod 依賴項。
  • 您的外掛在 Package.swift 檔案中顯式設定為 type: .dynamic

要更新您的單元測試

  1. 在 Xcode 中開啟您的 example/ios/Runner.xcworkspace

  2. 如果您正在為測試使用 CocoaPod 依賴項,例如 OCMock,您需要將其從 Podfile 檔案中刪除。

    ios/Podfile
    ruby
    target 'RunnerTests' do
      inherit! :search_paths
    
      pod 'OCMock', '3.5'
    end
    

    然後在終端中,在 plugin_name_ios/example/ios 目錄中執行 pod install

  3. 導航到專案的 Package Dependencies(包依賴項)。

    The project's package dependencies

    專案的包依賴項

  4. 單擊 + 按鈕,並透過在右上角的搜尋欄中搜索來新增任何僅用於測試的依賴項。

    Search for test-only dependencies

    搜尋僅用於測試的依賴項

  5. 確保將依賴項新增到 RunnerTests Target(目標)。

    Ensure the dependency is added to the `RunnerTests` target

    確保將依賴項新增到 RunnerTests 目標

  6. 單擊 Add Package(新增包)按鈕。

  7. 如果您已在 Package.swift 檔案中將外掛的庫型別顯式設定為 .dynamicApple 不推薦),您還需要將其作為依賴項新增到 RunnerTests 目標。

    1. 確保 RunnerTests Build Phases(構建階段)具有 Link Binary With Libraries(連結二進位制檔案與庫)構建階段

      The `Link Binary With Libraries` Build Phase in the `RunnerTests` target

      RunnerTests 目標的 Link Binary With Libraries 構建階段

      如果構建階段尚不存在,請建立一個。單擊 add 按鈕,然後單擊 New Link Binary With Libraries Phase(新建連結二進位制檔案與庫階段)。

      Add `Link Binary With Libraries` Build Phase

      新增 Link Binary With Libraries 構建階段

    2. 導航到專案的 Package Dependencies(包依賴項)。

    3. 單擊 add 按鈕。

    4. 在開啟的對話方塊中,單擊 Add Local...(新增本地...)按鈕。

    5. 導航到 plugin_name/plugin_name_ios/ios/plugin_name_ios,然後單擊 Add Package(新增包)按鈕。

    6. 確保將其新增到 RunnerTests 目標,然後單擊 Add Package(新增包)按鈕。

  8. 確保測試透過 Product > Test(產品 > 測試)。