передача данных из UIKit в SwiftUI (контроллер UIHostingController контейнера)

#swiftui

Вопрос:

Как передавать данные между UIViewController и struct ContentView ?

Я пробовал, ObservableObject но не могу обновить данные.

Комментарии:

1. Не могли бы вы подробнее рассказать о том, что вы пытаетесь сделать? Публикация исходного кода (того, что вы уже пробовали), безусловно, поможет.

2. Вы на это смотрели updateUIViewController(_:,context:) ?

3. в моем приложении(UIKit) есть представление, содержащее контейнер(Swiftui), и я хочу передать данные из моего представления(UIViewController) в мой контейнер(UIHostingController).

4. Вы можете прикрепить environmentObject к своему корневому представлению SwiftUI. Я напишу ответ, объясняющий, как его использовать.

Ответ №1:

Чтобы передать данные из a UIViewController в структуру SwiftUI внутри an UIHostingController , вы можете присоединить environmentObject ее к SwiftUI rootView :

 let vc = UIHostingController(rootView: YourContentView().environmentObject(yourEnvironmentObject))
 

Конечно, вам нужно будет создать объект ObservableObject и добавить его в свою SwiftUI-структуру.

Создайте объект ObservableОбъект:

 class TypeOfEnvironmentObject: ObservableObject {
    @Published var data = "myData"
}
 

Добавьте его в свою структуру:

 @EnvironmentObject var yourEnvironmentObject: TypeOfEnvironmentObject
 

Комментарии:

1. Спасибо! Ребята.. Да, я уже делал это раньше. Но когда значение данных обновляется, моя структура не принимает обновления, она остается со значением инициализации.

2. Хорошо, я думаю, я понял, что вы пытаетесь сделать. Если я вас правильно понял, объединенная структура-это то, что вы ищете: developer.apple.com/documentation/combine/…

3. С помощью Combine вы можете подключить издателя в вашем UIViewController к подписчику в вашей SwiftUI-структуре. Когда ваши данные изменятся, вы можете использовать издателя, чтобы уведомить подписчика.

4. Я пытаюсь, но я не понимаю концепции. Не могли бы вы привести мне небольшой пример?😅

5. большое вам спасибо, ребята, за ваши ответы. Я добился успеха ObservableObject и постараюсь подробно рассказать, может ли это помочь кому-то еще.

Ответ №2:

Я нашел существующие ответы запутанными/неполными, возможно, что-то изменилось вокруг общего вывода в Swift 5.3 и т. Д. Хотя вы можете добавить объект среды в представление UIHostingController, это, по-видимому, противоречит типам (т. Е. Общий параметр UIHostingController нуждается в конкретном типе). Добавление AnyView разрешает это:

 import UIKit
import SwiftUI

struct TutorialView: View {
    
    @EnvironmentObject private var integration: TutorialIntegrationService
    
    var body: some View {
        Text("Hi").navigationBarTitle("test: (integration.id)")
    }
}

class TutorialIntegrationService: ObservableObject {
    @Published var id: Int = 0
}

class TutorialViewController: UIHostingController<AnyView> {
    
    let integration = TutorialIntegrationService()
    
    required init?(coder: NSCoder) {
        super.init(coder: coder,rootView: AnyView(TutorialView().environmentObject(integration)));
    }
}
 

Ответ №3:

  1. class myclassname: ObservableObject
  2. в классе создайте переменную с @Published var myvar помощью и создайте init(myvar: type) {
    self.myvar = myvar
    }
  3. в моем UIViewController творении private var model = myclassname(myvar: XXX) и в viewWillAppear------>let vc = myclassname(myvar: myvar)
    let childView = UIHostingController(rootView: ContentView(model: vc))

    1. в моем struct ---> @ObservedObject var model: myclassname

Комментарии:

1. Это работает. Следует отметить, что если ваше представление принимает свойство $привязки (например, в предварительном просмотре вы используете @State), то $model.property будет работать вместо него, если вы выполните действия, описанные здесь.