Swift 包资源颜色在 CI 测试用例中返回为零。但是在本地测试用例中返回正常
Posted
技术标签:
【中文标题】Swift 包资源颜色在 CI 测试用例中返回为零。但是在本地测试用例中返回正常【英文标题】:Swift Package resource colors coming back as nil in CI test cases. But return fine during local test cases 【发布时间】:2020-12-11 04:25:44 【问题描述】:奇怪的是,这只发生在 CI (GitHub Actions) 上运行时。
这是我的资产目录:
这是我对 UIColor 的扩展以访问这些颜色:
// MARK: - UIKit
public extension UIColor
// MARK: Design System Colors
static let primaryColor = UIColor(named: "PrimaryColor", in: .module, compatibleWith: nil)!
static let primaryVariant = UIColor(named: "PrimaryVariant", in: .module, compatibleWith: nil)!
static let onPrimary = UIColor(named: "OnPrimary", in: .module, compatibleWith: nil)!
static let onPrimaryMedium = UIColor(named: "OnPrimaryMedium", in: .module, compatibleWith: nil)!
static let onPrimaryDisabled = UIColor(named: "OnPrimaryDisabled", in: .module, compatibleWith: nil)!
static let surface = UIColor(named: "Surface", in: .module, compatibleWith: nil)!
static let onSurface = UIColor(named: "OnSurface", in: .module, compatibleWith: nil)!
static let onSurfaceMedium = UIColor(named: "OnSurfaceMedium", in: .module, compatibleWith: nil)!
static let onSurfaceDisabled = UIColor(named: "OnSurfaceDisabled", in: .module, compatibleWith: nil)!
static let background = UIColor(named: "Background", in: .module, compatibleWith: nil)!
static let onBackground = UIColor(named: "OnBackground", in: .module, compatibleWith: nil)!
static let accent = UIColor(named: "Accent", in: .module, compatibleWith: nil)!
static let divider = UIColor(named: "Divider", in: .module, compatibleWith: nil)!
// MARK: Status Colors
static let statusSuccess = UIColor(named: "StatusSuccess", in: .module, compatibleWith: nil)!
static let statusWarning = UIColor(named: "StatusWarning", in: .module, compatibleWith: nil)!
static let statusError = UIColor(named: "StatusError", in: .module, compatibleWith: nil)!
// MARK: Map Colors
static let pinPlace = UIColor(named: "PinPlace", in: .module, compatibleWith: nil)!
static let pinRoute = UIColor(named: "PinRoute", in: .module, compatibleWith: nil)!
static let polyline = UIColor(named: "Polyline", in: .module, compatibleWith: nil)!
static let polylineRoute = UIColor(named: "PolylineRoute", in: .module, compatibleWith: nil)!
我有一个测试用例,它只遍历所有这些颜色并检查它们是否可以从模块包中加载(以便强制解包它们是安全的):
@testable import MyProject
import SwiftUI
import UIKit
import XCTest
/// Test to ensure that the colors can be loaded from the module bundle without crashing.
class MyProjectColorTest: XCTestCase
func testLoadUIColorFromBundle()
for color in UIColor.myProjectUIColors
XCTAssertNotNil(color)
fileprivate extension UIColor
static var myProjectUIColors: [UIColor] = [
UIColor.primaryColor,
UIColor.primaryVariant, //It fails when it tries to access this color.
UIColor.onPrimary,
UIColor.onPrimaryMedium,
UIColor.onPrimaryDisabled,
UIColor.surface,
UIColor.onSurface,
UIColor.onSurfaceMedium,
UIColor.onSurfaceDisabled,
UIColor.background,
UIColor.onBackground,
UIColor.accent,
UIColor.divider,
UIColor.statusSuccess,
UIColor.statusWarning,
UIColor.statusError,
UIColor.pinPlace,
UIColor.pinRoute,
UIColor.polyline,
UIColor.polylineRoute,
]
最后:
这是我的包清单:
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyProject",
defaultLocalization: "en",
platforms: [
.ios(.v13),
.watchOS(.v6),
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "MyProject",
targets: ["MyProject"]
),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "MyProject",
dependencies: [],
exclude: [
"MyProjectDemo/*",
],
// I've also tried omitting this and letting SPM handle it automatically.
resources: [
.process("*.xcassets"),
]
),
.testTarget(
name: "MyProjectTests",
dependencies: ["MyProject"]
),
]
)
另外,这是我的 GitHub 操作脚本:
name: Build
on:
push:
branches: [ master ]
paths:
- '.github/workflows/swiftlint.yml'
- '.swiftlint.yml'
- '**/*.swift'
pull_request:
branches: [ master, develop ]
paths:
- '.github/workflows/swiftlint.yml'
- '.swiftlint.yml'
- '**/*.swift'
jobs:
Build:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
- name: List available Xcode versions
run: ls /Applications | grep Xcode
- name: Select Xcode
run: sudo xcode-select -switch /Applications/Xcode_12.2.app
- name: Show Build Destinations
run: xcodebuild -showdestinations -scheme MyProject
- name: Build
run: xcodebuild test -scheme MyProject -destination 'platform=iOS Simulator,OS=14.2,name=iPhone 12'
Lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
- name: Lint
uses: norio-nomura/action-swiftlint@3.2.0
【问题讨论】:
【参考方案1】:有一个解决方法。在这里成立 -> https://developer.apple.com/forums/thread/664295
import Foundation
class CurrentBundleFinder
extension Foundation.Bundle
static var myModule: Bundle =
/* The name of your local package, prepended by "LocalPackages_" */
let bundleName = "UI_UI"
let candidates = [
/* Bundle should be present here when the package is linked into an App. */
Bundle.main.resourceURL,
/* Bundle should be present here when the package is linked into a framework. */
Bundle(for: CurrentBundleFinder.self).resourceURL,
/* For command-line tools. */
Bundle.main.bundleURL,
/* Bundle should be present here when running previews from a different package (this is the path to "…/Debug-iphonesimulator/"). */
Bundle(for: CurrentBundleFinder.self).resourceURL?.deletingLastPathComponent().deletingLastPathComponent(),
]
for candidate in candidates
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
if let bundle = bundlePath.flatMap(Bundle.init(url:))
return bundle
fatalError("unable to find bundle named \(bundleName)")
()
【讨论】:
以上是关于Swift 包资源颜色在 CI 测试用例中返回为零。但是在本地测试用例中返回正常的主要内容,如果未能解决你的问题,请参考以下文章