Как включить ресурсы/ресурсы в библиотеку диспетчера пакетов Swift?

Я хочу отправить свою библиотеку с помощью диспетчера пакетов Apple Swift. Однако моя библиотека содержит файл .bundle с несколькими строками, переведенными на разные языки. Используя cocoapods, я могу включить его, используя spec.resource. Но в SwiftPM я не могу этого сделать. Любое решение?

Ответ 1

Менеджер пакетов еще не имеет определения того, как ресурсы будут связаны с целями. Мы осознаем необходимость этого, но пока у него нет конкретного предложения. Я подал https://bugs.swift.org/browse/SR-2866, чтобы убедиться, что у нас есть ошибка, отслеживающая это.

Ответ 2

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

Пример:

Доступ к связанным ресурсам:

extension Bundle {
    static func myResourceBundle() throws -> Bundle {
        let bundles = Bundle.allBundles
        let bundlePaths = bundles.compactMap { $0.resourceURL?.appendingPathComponent("MyAssetBundle", isDirectory: false).appendingPathExtension("bundle") }

        guard let bundle = bundlePaths.compactMap({ Bundle(url: $0) }).first else {
            throw NSError(domain: "com.myframework", code: 404, userInfo: [NSLocalizedDescriptionKey: "Missing resource bundle"])
        }
        return bundle
    }
}

Используйте связанные ресурсы:

        let bundle = try! Bundle.myResourceBundle()
        return UIColor(named: "myColor", in: bundle, compatibleWith: nil)!

Вы можете применять одну и ту же логику ко всем файлам ресурсов, включая, помимо прочего, раскадровки, xib, изображения, цвета, большие двоичные объекты данных и файлы различных расширений (json, txt и т.д.).

Примечание: иногда это имеет смысл, иногда нет. Определите использование по собственному усмотрению проекта. Потребовались бы очень конкретные сценарии, чтобы оправдать разделение раскадровок /Xib на объединенные ресурсы.

Ответ 3

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

Предположим, что для тестирования ваших пакетов нужны какие-то фиктивные данные JSON. Вы поместите фиктивные JSON файлы в каталог Tests/JSONMocks. Затем в Package.swift:

targets: [
    .testTarget(
        name: "MyTargetTests",
        dependencies: ["MyTarget"],
        path: "Tests"
    ),
]

И загружать их динамически:

static func dataForJSONFileNamed(string: String) -> Data {
    // find mock JSON files if using Swift Package Manager:
    let currentDirectoryURL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
    let fileURL = currentDirectoryURL
        .appendingPathComponent("Tests", isDirectory: true)
        .appendingPathComponent("JSONMocks", isDirectory: true)
        .appendingPathComponent(string)
        .appendingPathExtension("json")
    let jsonFileData = try! Data(contentsOf: fileURL)
    return jsonFileData
}