Reputation: 10432
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
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
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
Reputation: 3088
extension Bundle {
static var current: Bundle {
class __ { }
return Bundle(for: __.self)
}
}
Upvotes: 27
Reputation: 6949
Updated for Swift 3.0+:
struct Foo {
class Bar {}
static var fooBundle: Bundle { return Bundle(for: Foo.Bar.self) }
}
Upvotes: 13
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