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

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

let bundle = NSBundle(forClass: self.dynamicType)

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

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

Ответы

Ответ 1

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

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

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

Если вам нужно "следовать за поиском пакетов" для структуры (или перечисления), одним из способов, которые могут оказаться полезными, является определение класса как подтипа:

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

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

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

Ответ 2

Обновлено для Swift 3. 0+:

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

Ответ 3

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

Ответ 4

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")!
}

Ответ 5

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

Класс NSBundle ожидает всегда одного класса, который является подмножеством NSObject, в этом случае только классы могут наследовать его.

Попробуйте использовать структуру, если экземпляры типа являются малыми и обычно недолговечными или обычно внедряются в другие объекты. для других случаев используйте класс.

Обычно я использую только структуры в случае:

  • Модели и объекты объектов
  • Неизменяемость (не для всех, но в большинстве случаев)
  • Размер экземпляра не более 16 байт.