Импортировать пакет SwiftUI сообщества с целью 13.0 в проекте iOS 10+ - PullRequest
1 голос
/ 28 мая 2020

Я работаю над проектом iOS, который должен поддерживать iOS 10+. Я хотел бы создать некоторые новые функции с помощью SwiftUI и сделать их доступными только для наших пользователей iOS 13+, используя @available(iOS 13.0, *). Это прекрасно работает, пока я использую только готовые компоненты.

Однако при импорте компонента SwiftUI от сообщества, предназначенного для iOS 13 и более поздних версий, я получаю следующую ошибку:

Error as shown in XCode

Compiling for iOS 10.0, but module 'SwiftUIPager' has a minimum deployment target of iOS 13.0: 
DerivedData/MyApp-qbarasdasdaasdbsp/Build/Products/Debug-iphonesimulator/SwiftUIPager.swiftmodule/x86_64-apple-ios-simulator.swiftmodule

Это имеет смысл, потому что в модуле установлено iOS 13+ как SupportedPlatform. Я предложил автору снизить целевое значение до iOS 10 и добавить везде @available(iOS 13.0, *), но, конечно, это тоже не идеально, поскольку делает атрибут SupportedPlatform SPM бесполезным.

Есть ли способ включить подобные пакеты в проект, который хочет поддерживать более низкую цель, чем поддерживает пакет? Является ли это недостатком в конструкции файла манифеста пакета Swift?

1 Ответ

1 голос
/ 29 мая 2020

Вот рабочее решение. Протестировано с помощью Xcode 11.4 / iOS 13.4

1) Создайте целевой фреймворк iOS (назовем его ModernProxy для справки) с целью развертывания> 13.0 и сделайте его зависимым от современного пакета на основе SwiftUI (ModernLibrary в эта демонстрация), как в примере ниже

demo1

2) Сделайте встроенную в устаревшую целевую среду современную структуру, как в примере ниже

demo2

3) В ModelProxy framework создайте класс контроллера с не аргументом по умолчанию init, который обертывает SwiftUI root UIHostingController с видом из внешнего пакета, как в примере ниже

import SwiftUI
import ModernLibrary // SwiftUI based external package

public class ModernProxyController: UIHostingController<ModernView> {
    public init() {
        super.init(rootView: ModernView())
    }

    @objc required dynamic init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

и сделайте этот контроллер основным классом фреймворка (на самом деле в более сложном случае основной класс может играть некоторую фабричную роль, чтобы возвращать множество контроллеров по протоколу, но вот один для простоты)

demo3

4) В вашем основном целевом ViewController (тот, в который вы хотите внедрить современный вид SwiftUI) загружайте динамически пакет прокси-фреймворка и создайте экземпляр contr oller через основной класс, как в примере ниже

class ViewController : UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // ... any other code here

        if #available(iOS 13.0, *) {
            if let proxyClass = Bundle(identifier: "com.Testing.ModernProxy")?.principalClass as? UIViewController.Type {
                let controller = proxyClass.init()
                self.addChild(controller)
                controller.view.translatesAutoresizingMaskIntoConstraints = false
                view.addSubview(controller.view)
                // ... add any needed constraints
            }
        } else {
            // Fallback on earlier versions
        }
    }

    // ... other controller code here
...