Как получить пакет для структуры?

В Swift вы можете позвонить

let bundle = NSBundle(forClass: self.dynamicType)

в любом классе и получить актуальную связку. Если вы NSBundle.mainBundle() не сможете получить правильный пакет, например, при выполнении модульных тестов.

Итак, как вы можете получить текущий пакет для Swift struct?


person bogen    schedule 09.07.2015    source источник
comment
Также ищу ответ на этот вопрос. В настоящее время у меня есть определение класса-заполнителя и расширение NSBundle, помогающее, поэтому я могу продолжать работать, пока не будет найдено правильное решение.   -  person Max Chuquimia    schedule 12.08.2015


Ответы (5)


Лучшее решение здесь зависит от того, для чего вам нужен пакет.

Это поиск ресурсов, существующих только в определенном приложении, фреймворке или пакете расширений, которые, как известно, загружаются при запуске кода, который вы пишете? В этом случае вы можете использовать init(identifier:) вместо динамического поиска пакета, определяющего определенный тип.

Остерегайтесь поиска пакетов "следует за типом". Например, если класс фреймворка Foo использует NSBundle(forClass: self.dynamicType) для загрузки ресурса, подкласс Foo, определенный приложением, загружающим этот фреймворк, в конечном итоге будет искать в пакете приложения, а не в пакете фреймворка.

Если вам нужен поиск пакета «следует за типом» для структуры (или перечисления), один обходной путь, который может оказаться полезным, — это определить класс как подтип:

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

Обратите внимание, что здесь нет ничего динамического, потому что ничего не должно быть — каждый Foo исходит из определения одного и того же типа (поскольку структуры не могут наследоваться), поэтому его статический тип соответствует его динамическому типу.

(Следует признать, что NSBundle(forType:), который может обрабатывать структуры, перечисления и протоколы, мог бы сделать хороший запрос функции. Хотя я полагаю, что это может быть сложно сделать он обрабатывает расширения и все такое...)

person rickster    schedule 22.03.2016
comment
будет ли работать статический fooBundle = Bundle(for: Foo.Bar.self)? @рикстер - person Kirill Kudaev; 28.04.2019
comment
Да, это выглядит работоспособным. (Мой первоначальный ответ предшествовал переименованию NSBundle в Bundle для Swift.) Однако не стесняйтесь проверить его. - person rickster; 28.04.2019

Обновлено для Swift 3.0+:

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

Свифт 5

struct Foo {
    class Bar {}
    static var fooBundle: Bundle { return Bundle(for: Foo.Bar.self) }
}
person Oleh Kudinov    schedule 05.12.2019

Свифт 4+

Вы можете сделать let bundle = InternalConstants.bundle, если добавите эту структуру в свой проект. На мой взгляд, очень элегантное решение.

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

Другое потенциальное решение (менее элегантное):

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

person    schedule
comment
Спасибо! Работает на Xcode 11.7 + SwiftUI в Live Preview - person Wamasa; 11.11.2020