SwiftUI с UIViewControllerRepresentable

Я пытаюсь использовать UIViewController, представленный в проекте swiftUi. В частности, я пытаюсь нажать одну кнопку (assetOne), которая позволяет ЕС выбрать видео, а затем нажать другую кнопку (assetTwo), и это позволяет пользователю выбрать другое видео. Затем у пользователя будет возможность объединить видео (с помощью третьей кнопки). Я предположил, что для этого мне понадобится координатор, но, увидев решение SO без него, я попытался сделать это без него. Но когда я запускаю свой проект, сборка выполняется успешно, но когда я нажимаю любую из кнопок в представлении содержимого, я получаю сообщение об ошибке ниже. Что я делаю неправильно? Нужен ли мне координатор и как включить его в мою текущую конфигурацию?

Предупреждение: Попытка представить в , представление которого не входит в иерархию окон!

Просмотр содержания:

import SwiftUI

struct ContentView: View {
    
    let someView = ImagePicker()
    
    var body: some View {
        VStack {
            Button(action: {
                print("SwiftUI: assetOne button tapped")
                // Call func in SomeView()
                self.someView.assetOne()
            }) {
                Text("Asset One").foregroundColor(Color.black)
            }
            .background(Color.blue)
            .padding(10)
            .clipShape(Capsule())
}
//...

ImagePicker: UIViewControllerRepresentable

struct ImagePicker: UIViewControllerRepresentable{
    
    let someView = MergeVideoViewController()

func makeUIViewController(context: Context) -> MergeVideoViewController {
      someView
    }

    func updateUIViewController(_ uiViewController: MergeVideoViewController, context: Context) {}
    
    func assetOne() {
        someView.loadAssetOne()
    }
    //...
}

Мой класс UIViewController:

class MergeVideoViewController: UIViewController {
    var firstAsset: AVAsset?
    var secondAsset: AVAsset?
    var audioAsset: AVAsset?
    var loadingAssetOne = false
    var activityMonitor: UIActivityIndicatorView!
    
func exportDidFinish(_ session: AVAssetExportSession) {
    // Cleanup assets
    activityMonitor.stopAnimating()
    firstAsset = nil
    secondAsset = nil
    audioAsset = nil

//...

func loadAssetOne() {
        //  func loadAssetOne(_ sender: AnyObject) {
        if savedPhotosAvailable() {
            loadingAssetOne = true
            VideoHelper.startMediaBrowser(delegate: self, sourceType: .savedPhotosAlbum)
        }
    }

//...

1 ответ

В ImagePicker is-a View, он должен быть где-то в body.

Вот возможный подход - идея состоит в том, чтобы получить ссылку на контроллер обратно в SwiftUI и при необходимости напрямую вызвать его действия.

struct ImagePicker: UIViewControllerRepresentable{
    let configure: (MergeVideoViewController) -> ()

    func makeUIViewController(context: Context) -> MergeVideoViewController {
       let someView = MergeVideoViewController()
       configure(someView)
       return someView
    }

    func updateUIViewController(_ uiViewController: MergeVideoViewController, context: Context) {}
}

struct ContentView: View {

    @State private var controller: MergeVideoViewController?

    var body: some View {
        VStack {
            ImagePicker {
                self.controller = $0
            }

            Button(action: {
                print("SwiftUI: assetOne button tapped")
                self.controller?.loadAssetOne()
            }) {
                Text("Asset One").foregroundColor(Color.black)
            }
            .background(Color.blue)
            .padding(10)
            .clipShape(Capsule())
        }
    }
}

Другие вопросы по тегам