48

I am working on a framework for iOS, which comes with some datafiles. To load them into a Dictionary I do something like this:

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
}

If I use this in a playground with the framework, it works as intended.

But if I use the framework embedded in an app, it doesn't work anymore, the "path" now points to the bundle of the app, not of the framework.

How do I make sure that the bundle of the framework is accessed?

EDIT: the code above resides in the framework, not in the app.

EDIT2: the code above is a utility function, and is not part of a struct or class.

koen
  • 5,383
  • 7
  • 50
  • 89

5 Answers5

100

Use Bundle(for:Type):

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

or search the bundle by identifier (the frameworks bundle ID):

let bundle = Bundle(identifier: "com.myframework")
shallowThought
  • 19,212
  • 9
  • 65
  • 112
11

Swift 5

let bundle = Bundle(for: Self.self)
let path = bundle.path(forResource: "filename", ofType: ".plist")
Oleh Kudinov
  • 2,533
  • 28
  • 30
6

Try below code to get the custom bundle:

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

Update

If in your framework, try this:

[[NSBundle bundleForClass:[YourClass class]] URLForResource:@"YourResourceName" withExtension:@".suffixName"];
Adrian
  • 16,233
  • 18
  • 112
  • 180
aircraft
  • 25,146
  • 28
  • 91
  • 166
4

Simply specify the class name of the resource and below function will give you the Bundle object with which the class is associated with, so if class is associated with a framework it will give bundle of the framework.

let bundle = Bundle(for: <YourClassName>.self)
  • Not applicable to my question, see the comments to the answer of @aircraft below. – koen Mar 27 '19 at 12:23
  • YourClassName is the class of resource or xib name and is a better way of getting bundle rather than search by bundle identifier. – Samuel Paul Mar 27 '19 at 15:54
  • I am loading a plist with lots of data. Please explain how this relates to `YourClassName` – koen Mar 27 '19 at 16:06
  • it is related to your question, in you case it's a plist but someone else might want to get the bundle from a resource and might come here to look for the answer. – Samuel Paul Mar 27 '19 at 16:10
  • Sure, but that's not how SO works. In that case it is better to ask a separate question. – koen Mar 27 '19 at 17:55
  • Take it easy, you don't have to accept this as the answer, as I said it's related to your question and someone else might find it useful, i am only trying to help. – Samuel Paul Mar 28 '19 at 04:43
1
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")
    }()
}

From: Source

---Update---

It provides 3 kind of most comment usages about how to get the correct bundle, this is very useful especially when you are developing your own framework or using Cocoapods.

irons163
  • 54
  • 6
  • Please add some explanation why you think this is a useful answer. – koen May 09 '21 at 18:23
  • @koen, apparently, It provides 3 kind of most comment usages about how to get the correct bundle, this is very useful especially when you are developing your own framework or using Cocoapods. – irons163 May 11 '21 at 03:15
  • Please [edit] your answer to include your explanations. – koen May 14 '21 at 00:06