【问题标题】:Generating resource_bundle_accessor, Type 'Bundle' has no member 'module'生成resource_bundle_accessor,类型'Bundle'没有成员'module'
【发布时间】:2020-08-03 21:46:36
【问题描述】:

有时 Xcode 无法确定 Bundle 中的module 参数。

类型“Bundle”没有成员“模块”

我的调查表明,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

更新

有时会显示:

“模块”由于“内部”保护级别而无法访问

而且它根本没有显示文件。

【问题讨论】:

  • 这个 resource_bundle_accessor 文件在哪里?我尝试了答案中建议的所有内容,但它不起作用。不如自己创造吧。
  • 不,你不能自己创建它!!!它是自动生成的,这是问题的重点。
  • 我今天早上实际上在这里发布了一个相关问题:stackoverflow.com/questions/64403646/… - 也许您可以在我的Package.swift 文件中发现错误?

标签: swift xcode bundle swift-package-manager


【解决方案1】:

仅当对应的目标包含resources 作为参数时,SPM 才会生成 resource_bundle_accessor

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

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

和❗️

项目必须实际上包含Resources内部目标目录!

和❗️❗️

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

【讨论】:

  • 我花了几个小时寻找正确的答案!但终于奏效了!谢谢?
  • 未来的读者,这些解决方案似乎不适用于 Swift 5.5 和可执行目标:cf。 this comment on a bug report 和我自己的经验?
  • 它对我有用,谢谢
【解决方案2】:

如果您看到这样的错误:

错误:找到 1 个未处理的文件;明确将它们声明为资源或从目标中排除

类型“Bundle”没有成员“模块”

然后复习以下五个条件:

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 文件是否声明了一个资源元素,如下所示:

.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 database for SPM

【讨论】:

  • 第一个条件解决了我的问题,谢谢:)
【解决方案3】:

好的,我找到了解决方案,所以 Swift 实际上生成了Bundle.module 文件?

documentation 明确指出您必须将您的Resources 放在文件夹&lt;project_root&gt;/Sources/&lt;MyTarget&gt;/ 下,因为 SPM 按目标确定资源范围。我的 repo SHSearchBar 的目标定义看起来像这样(比较 Github 上的文件结构):

// swift-tools-version:5.3
import PackageDescription


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

目标文件夹:&lt;project_root&gt;/Sources/SHSearchBar
资源文件夹:&lt;project_root&gt;/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

【讨论】:

  • 不要犯我犯的错误:确保你的包文件顶部有// swift-tools-version:5.3或更大,而不是swift-tools-version:5.1,因为它是从另一个包复制的一个模板。如果不是5.3或以上,则不会生成Bundle,错误信息也不是很清楚。
【解决方案4】:

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 或不同的目标子文件夹。

【讨论】:

    【解决方案5】:

    您还可以通过使用静态 let 创建一个类来公开捆绑包:

    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")
    

    【讨论】:

      猜你喜欢
      • 2015-08-14
      • 1970-01-01
      • 2016-09-18
      • 2019-02-18
      • 2019-02-18
      • 2019-09-17
      • 2019-04-27
      相关资源
      最近更新 更多