swift 正在生成resource_bundle_accessor,类型“捆绑包”没有成员“模块”

anauzrmj  于 2023-02-18  发布在  Swift
关注(0)|答案(7)|浏览(172)

有时Xcode无法确定Bundle中的module参数。
类型"Bundle"没有成员"module"
我的调查显示SPM在模块上为这个属性自动生成一个扩展名(有时),文件名为 * resource_bundle_accessor *,如下所示:

import class Foundation.Bundle

private class BundleFinder {}

extension Foundation.Bundle {
    /// Returns the resource bundle associated with the current Swift module.
    static var module: Bundle = {
        let bundleName = "ABUIKit_ABStyleKit"

        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: BundleFinder.self).resourceURL,

            // For command-line tools.
            Bundle.main.bundleURL,
        ]

        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 ABUIKit_ABStyleKit")
    }()
}

但有时候它不会。为什么会这样?我怎样才能让它自动工作再次(而不需要手动实现)。
这两种情况都发生在Xcode 12 beta.3

更新

有时它显示:
由于"内部"保护级别,无法访问"模块"
它根本不显示文件。

cgvd09ve

cgvd09ve1#

SPM仅在相应目标包含resources作为参数时生成 * resource_bundle_accessor *,如下所示:

.target(
        name: "ChenzookKit",
        dependencies: ["Apollo"],
        resources: [.process("Resources")] // <- `copy` or `process` doesn't really matter 
    ),

另外,请注意它应该是有效的资源路径。

和️

项目必须实际上在目标的目录中包含Resources

和#️#️

不要忘记构建(cmd+b)代码来创建.module

3vpjnl9f

3vpjnl9f2#

如果您看到如下错误:
错误:找到1个未处理的文件;显式声明它们为资源或从目标中排除
类型"Bundle"没有成员"module"
然后检查以下五种情况:

    • 1.**检查Package. swift的第一行是否声明使用swift-tools-version:5.3或更高版本。
// swift-tools-version:5.3
    • 2.**检查资源文件夹是否在目标文件夹下。例如,
Sources/MyTarget/Resources
Tests/MyTargetTests/Resources
    • 3.**检查是否已添加至少一个资源。例如,
Tests/MyTargetTests/Resources/paginatedLabels.json
    • 4.**通过使用Xcode打开文件Package.swift来检查您是否打开了该包。
    • 5.**检查Package.swift文件是否声明了一个resources元素,如下所示:
.testTarget(
    name: "MyTargetTests",
    dependencies: ["MyTarget"],
    resources: [
        .process("Resources")
    ]
),

此时,编译器合成了一个包含以下内容的文件resource_bundle_accessor.swift

extension Foundation.Bundle {
    static var module: Bundle = {
...

要检查文件是否确实已合成:

# is the bundle being synthesized when you build?
find ~/Library/Developer/Xcode/DerivedData* -iname resource_bundle_accessor.swift

要从软件包中加载资源,请使用Bundle.module,例如:

UIImage(named: "share", in: Bundle.module, compatibleWith: nil)

查找软件包捆绑包目录的路径:

MODULE=MyModuleName && find -E ~/Library/Developer/Xcode/DerivedData -regex ".*$MODULE_$MODULE.bundle"

要检查软件包捆绑包是否包含特定资源,例如图像:

# I’m building for iPhone 12 (@3x). Is share@3x.png inside the bundle?
find ~/Library/Developer/Xcode/DerivedData* -iname Assets.car -exec xcrun --sdk iphoneos assetutil --info {} \; | grep -E "share.*png"

以下是使用自定义目录的示例:

targets: [
    .target(
        name: "Kit",
        dependencies: [],
        path: "sources/main",
        resources: [
            .process("resources")
        ]
    ),

其中目录包括:

Kit/
├── sources/
│   └── main/
│       ├── SourceFile.swift
│       └── resources/
│           └── file.json
└── Package.swift

如果一切都失败了,您怀疑有bug,请检查bug database for SPM

8ftvxx2r

8ftvxx2r3#

好了,我找到了一个解决方案,Swift实际上生成了Bundle.module文件🎉
documentation明确指出,由于SPM按目标来确定资源的范围,因此必须将Resources放在文件夹<project_root>/Sources/<MyTarget>/下,我的repo SHSearchBar的目标定义如下所示(比较Github上的文件结构):

// swift-tools-version:5.3
import PackageDescription

    targets: [
        .target(
            name: "SHSearchBar",
            resources: [.copy("Resources")]
        )
    ]

目标文件夹:<project_root>/Sources/SHSearchBar
资源文件夹:<project_root>/Sources/SHSearchBar/Resources
顺便说一下,要从命令行构建iOS包,您可以使用此命令使用iOS 14 SDK:

swift build -Xswiftc "-sdk" -Xswiftc "\`xcrun --sdk iphonesimulator --show-sdk-path\`" -Xswiftc "-target" -Xswiftc "x86_64-apple-ios14.0-simulator"

为了使我的小文章完整,我还想提一下,使用Bundle.module方法的包也可以集成到运行在iOS〈14的应用程序中,因为生成的扩展不包含任何新的API👍

sc4hvdpw

sc4hvdpw4#

Bundle.module仅在Package.swift文件中的resources不为空指定资源实际存在时由SwiftPM生成。
因此,有两个可能的原因说明它可能不适合您:
1.您没有在Package.swift中指定任何resources。修复如下:

.target(
    name: "MyLibrary",
    dependencies: [
        /* your dependencies */
    ],
    resources: [
        .copy("JsonData"),
        .process("Assets.xcassets"),
    ]
),

1.指定的路径不存在或为空。
通过检查你是否已经把你的资源**放到Sources/MyLibrary**目录中来修复。一个常见的错误是把它们直接放到Sources或其他目标子文件夹中。

xmd2e60i

xmd2e60i5#

您也可以通过创建一个带有static let的类来公开bundle:

public class YourPackageBundle {
   public static let yourPackageBundle = Bundle.module
}

然后,您可以在公共类中访问它并使用它:

public init(backgroundImage: Image? = nil,
            logoImage: Image? = nil,
            userIconImage: Image? = nil,
            userTextFieldPlaceholder:String = NSLocalizedString("global_username", bundle: YourPackageBundle.yourPackageBundle, comment: "User placeholder text")
gojuced7

gojuced76#

在我的例子中,我尝试了所有的解决方案,但在重新启动Xcode之前没有任何帮助。
在Xcode 14.0.0上完成

oipij1gg

oipij1gg7#

1.确保Resources文件夹存在并且其中包含文件
1.当Resources文件夹不为空时,XCode会自动生成Bundle.module。但它是internal
1.添加@testable import YourPackage to make可以使包源代码中的内部文件可用于测试。

相关问题