Делегат для SwiftUI View из Hosting View Controller

Я добавляю UIHostingViewController в свою раскадровку и создаю для этого класс. Загрузите mySwiftUIView в init контроллера. Все работает хорошо.

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

required init?(coder: NSCoder) {
    var mySwiftView = MySwiftUIView()
    mySwiftView.delegate = self //self used before super.init call
    super.init(coder: coder,rootView: mySwiftView)
}

Id не работает, потому что я передаю просмотр до полной инициализации хост-контроллера. Swift показывает сообщение "используется до вызова super.init"

Если я воспользуюсь обычным UIViewController и поставлю HostingController внутрь - все работает. Но мне это не подходит, потому что вызывает проблемы с размерами и навигацией.

Как это сделать с отдельным UIHostingController. благодаря

Полный код

import UIKit
import SwiftUI

protocol MySwiftUIViewDelegate{
    func buttonPressed()
}

struct MySwiftUIView: View {
    var delegate: MySwiftUIViewDelegate?
    
    var body: some View {
        Button(action: {
            delegate?.buttonPressed()
        }) {
            Text("My button")
        }
    }
}

class MyHostingViewController: UIHostingController<MySwiftUIView>, MySwiftUIViewDelegate {
        
required init?(coder: NSCoder) {
    var mySwiftView = MySwiftUIView()
    //mySwiftView.delegate = self //self used before super.init call
    super.init(coder: coder,rootView: mySwiftView)
}

override func viewDidLoad() {
    super.viewDidLoad()
}

func buttonPressed() {
    performSegue(withIdentifier: "GoToOtherScreenSegue", sender: self)
}
}

2 ответа

Решение

Поскольку MyHostingViewController знает, что это rootView является MySwiftUIView, вы можете впоследствии назначить контроллер представления в качестве делегата:

required init?(coder: NSCoder) {
    var mySwiftView = MySwiftUIView()
    super.init(coder: coder, rootView: mySwiftView)
    rootView.delegate = self
}

Вы можете обернуть делегата в класс

      import UIKit
import SwiftUI

protocol MySwiftUIViewDelegate{
    func buttonPressed()
}

struct MySwiftUIView: View {
    let configuration: Configuration
    
    var body: some View {
        Button(action: {
            configuration.delegate?.buttonPressed()
        }) {
            Text("My button")
        }
    }
}

extension MySwiftUIView {
    final class Configuration {
        unowned var delegate: MySwiftUIViewDelegate?
    }
}

class MyHostingViewController: UIHostingController<MySwiftUIView>, MySwiftUIViewDelegate {
        
    required init?(coder: NSCoder) {
        let configuration = MySwiftUIView.Configuration()
        let mySwiftView = MySwiftUIView(configuration: configuration)
        super.init(coder: coder,rootView: mySwiftView)
        configuration.delegate = self
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func buttonPressed() {
        performSegue(withIdentifier: "GoToOtherScreenSegue", sender: self)
    }
}
Другие вопросы по тегам