Strangely, this only happens when running on CI (GitHub Actions).
here is my asset catalog:
Here is my extension to UIColor to access these colors:
// 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)!
}
I have a test case that just runs through all these colors and checks if they can be loaded from the module bundle (so that its safe to force unwrap them):
@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,
]
}
Finally:
Here is my package manifest:
// 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"]
),
]
)
Also, here's my GitHub action script:
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/[email protected]
- 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/[email protected]
- name: Lint
uses: norio-nomura/[email protected]