【问题标题】:Path to bundle of iOS frameworkiOS 框架包的路径
【发布时间】:2017-10-20 12:37:34
【问题描述】:

我正在开发一个带有一些数据文件的 iOS 框架。要将它们加载到 Dictionary 中,我会这样做:

public func loadPListFromBundle(filename: String, type: String) -> [String : AnyObject]? {
    guard
       let bundle = Bundle(for: "com.myframework")
       let path = bundle.main.path(forResource: filename, ofType: type),
       let plistDict = NSDictionary(contentsOfFile: path) as? [String : AnyObject]
    else { 
       print("plist not found")
       return nil 
    }

    return plistDict
}

如果我在带有框架的游乐场中使用它,它会按预期工作。

但是如果我使用嵌入在应用程序中的框架,它就不再起作用了,“路径”现在指向应用程序的包,而不是框架。

如何确保框架的捆绑包被访问?

编辑:上面的代码驻留在框架中,而不是在应用程序中。

EDIT2:上面的代码是一个实用函数,不是结构或类的一部分。

【问题讨论】:

  • 如果您在自定义框架中,则无法获取主包的路径,不是那种方式。

标签: ios swift frameworks bundle


【解决方案1】:

使用Bundle(for:Type):

let bundle = Bundle(for: type(of: self))
let path = bundle.path(forResource: filename, ofType: type)

或通过 identifier(框架包 ID)搜索包:

let bundle = Bundle(identifier: "com.myframework")

【讨论】:

  • 代码不是类或结构的一部分,所以没有self。我已经编辑了我的问题。
  • 更新答案。
  • 谢谢,使用Bundle(identifier: "com.myframework") 成功了。
【解决方案2】:
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 = "ID3TagEditor_ID3TagEditorTests"

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

发件人:Source

---更新---

它提供了 3 种关于如何获取正确捆绑包的大多数注释用法,这非常有用,尤其是在您开发自己的框架或使用 Cocoapods 时。

【讨论】:

  • 请添加一些解释,为什么您认为这是一个有用的答案。
  • @koen,显然,它提供了 3 种关于如何获取正确包的大多数评论用法,这非常有用,尤其是在您开发自己的框架或使用 Cocoapods 时。
  • 请edit你的答案包括你的解释。
【解决方案3】:

斯威夫特 5

let bundle = Bundle(for: Self.self)
let path = bundle.path(forResource: "filename", ofType: ".plist")

【讨论】:

    【解决方案4】:

    只需指定资源的类名,下面的函数将为您提供与该类关联的 Bundle 对象,因此如果类与框架关联,它将提供框架的捆绑包。

    let bundle = Bundle(for: <YourClassName>.self)
    

    【讨论】:

    • 不适用于我的问题,请参阅下面@aircraft 答案的 cmets。
    • YourClassName 是资源类或 xib 名称,是获取捆绑包而不是通过捆绑包标识符搜索的更好方法。
    • 我正在加载一个包含大量数据的 plist。请解释这与YourClassName 有何关系
    • 它与您的问题有关,在您的情况下,它是一个 plist,但其他人可能想从资源中获取捆绑包并可能会来这里寻找答案。
    • 当然,但这不是 SO 的工作方式。在这种情况下,最好单独提出一个问题。
    【解决方案5】:

    尝试下面的代码来获取自定义包:

    let bundlePath = Bundle.main.path(forResource: "CustomBunlde", ofType: "bundle")
    let resourceBundle = Bundle.init(path: bundlePath!)
    

    更新

    如果在你的框架中,试试这个:

    [[NSBundle bundleForClass:[YourClass class]] URLForResource:@"YourResourceName" withExtension:@".suffixName"];
    

    【讨论】:

    • 访问包的代码在框架中,而不是在应用程序中。
    • YourClass 是什么?
    • @Koen 测试[self class]
    • @Koen 在38-line看到这个链接,很久以前就和作者交流过:github.com/pikacode/EBForeNotification/blob/master/…
    • 我不明白class 是什么; loadPListFromBundle 只是一个实用函数(在Swift 中,顺便说一句)。
    猜你喜欢
    • 2012-06-05
    • 2012-04-22
    • 1970-01-01
    • 2020-11-05
    • 1970-01-01
    • 2013-09-14
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    相关资源
    最近更新 更多