bogen
bogen

Reputation: 10432

How to get bundle for a struct?

In Swift, you can call

let bundle = NSBundle(forClass: self.dynamicType)

in any class and get the current bundle. If you NSBundle.mainBundle() this will fail getting correct bundle when for example running unit tests.

So how can you get the current bundle for a Swift struct?

Upvotes: 40

Views: 11422

Answers (5)

Pranav Kasetti
Pranav Kasetti

Reputation: 9935

For Swift Packages, we get the Bundle where the Swift struct is declared anywhere in the same module (target) via:

Bundle.module

However, we need to import a resource in the Package to get this autogenerated.

Bundle.main also works for other projects if you don't have extension targets.

Upvotes: 4

Kirill
Kirill

Reputation: 889

Swift 4+

You can do let bundle = InternalConstants.bundle if you add this struct to your project. A very elegant solution in my opinion.

internal struct InternalConstants {
    private class EmptyClass {}
    static let bundle = Bundle(for: InternalConstants.EmptyClass.self)
}

Another potential solution (less elegant):

internal struct InternalConstants {
    internal static let bundle = Bundle(identifier: "com.hello.world")!
}

Upvotes: 3

Valentyn Zakharenko
Valentyn Zakharenko

Reputation: 3088

extension Bundle {
    static var current: Bundle {
        class __ { }
        return Bundle(for: __.self)
    }
}

Upvotes: 27

NatashaTheRobot
NatashaTheRobot

Reputation: 6949

Updated for Swift 3.0+:

struct Foo {
     class Bar {}
     static var fooBundle: Bundle { return Bundle(for: Foo.Bar.self) }
}

Upvotes: 13

rickster
rickster

Reputation: 126167

The best solution here depends on what you need a bundle for.

Is it to look up resources that exist only in a specific app, framework, or extension bundle that's known to be loaded when the code you're writing runs? In that case you might want to use init(identifier:) instead of dynamically looking up the bundle that defines a certain type.

Beware of "follows the type" bundle lookups. For example, if a framework class Foo uses NSBundle(forClass: self.dynamicType) to load a resource, a subclass of Foo defined by the app loading that framework will end up looking in the app bundle instead of the framework bundle.

If you do need a "follows the type" bundle lookup for a struct (or enum), one workaround that might prove helpful is to define a class as a subtype:

struct Foo {
     class Bar {}
     static var fooBundle: NSBundle { return NSBundle(forClass: Foo.Bar.self) }
}

Note there's nothing dynamic here, because nothing needs to be — every Foo comes from the same type definition (because structs can't inherit), so its static type matches its dynamic type.

(Admittedly, an NSBundle(forType:) that could handle structs, enums, and protocols might make a nice feature request. Though I imagine it could be tricky to make it handle extensions and everything...)

Upvotes: 33

Related Questions