Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 965
bogen Avatar asked Jul 09 '15 11:07

bogen


5 Answers

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

like image 188
rickster Avatar answered Oct 17 '22 18:10

rickster


extension Bundle {
    static var current: Bundle {
        class __ { }
        return Bundle(for: __.self)
    }
}
like image 37
Valentine Zakharenko Avatar answered Oct 17 '22 17:10

Valentine Zakharenko


Updated for Swift 3.0+:

struct Foo {
     class Bar {}
     static var fooBundle: Bundle { return Bundle(for: Foo.Bar.self) }
}
like image 11
NatashaTheRobot Avatar answered Oct 17 '22 17:10

NatashaTheRobot


Swift 5

struct Foo {
    class Bar {}
    static var fooBundle: Bundle { return Bundle(for: Foo.Bar.self) }
}
like image 4
Oleh Kudinov Avatar answered Oct 17 '22 19:10

Oleh Kudinov


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.

like image 2
Pranav Kasetti Avatar answered Oct 17 '22 18:10

Pranav Kasetti