SwiftUI:为每个视图使用不同的环境对象
在SwiftUI中,我有两个不同的屏幕。对于每个屏幕,我都有一个ViewController、SwiftUI视图和一个组合环境对象。组合的EnvironmentObject有两个可观察的类,一个是ViewModel,另一个是Interactior 在不使用ViewController的情况下,如何为每个SwiftUI视图使用Interactior和ViewModel?每个视图都有不同的EnvironmentObjectSwiftUI:为每个视图使用不同的环境对象,swiftui,swift5,Swiftui,Swift5,在SwiftUI中,我有两个不同的屏幕。对于每个屏幕,我都有一个ViewController、SwiftUI视图和一个组合环境对象。组合的EnvironmentObject有两个可观察的类,一个是ViewModel,另一个是Interactior 在不使用ViewController的情况下,如何为每个SwiftUI视图使用Interactior和ViewModel?每个视图都有不同的EnvironmentObject import SwiftUI import Combine class V
import SwiftUI
import Combine
class ViewModel1: ObservableObject {
//Published data for view
@Published var text: String
init(text: String) {
self.text = text
}
}
class Interactor1<VC: UIViewController>: ObservableObject {
let vc: VC
let viewModel: ViewModel1?
init(vc: VC, viewModel: ViewModel1?) {
self.vc = vc
self.viewModel = viewModel
}
func buttonClicked() {
//present second ViewController by using vc.present...
}
}
class CombinedObject<VC: UIViewController>: ObservableObject {
@Published var interactor: Interactor1<VC>
@Published var viewModel: ViewModel1
var anyCancellable: AnyCancellable? = nil
var anyCancellable2: AnyCancellable? = nil
init(vc: VC, index: Int) {
viewModel = ViewModel1(text: "text1")
interactor = Interactor1(vc: vc, viewModel: nil)
interactor = Interactor1(vc: vc, viewModel: viewModel)
anyCancellable = interactor.objectWillChange.sink { (_) in
self.objectWillChange.send()
}
anyCancellable2 = viewModel.objectWillChange.sink { (_) in
self.objectWillChange.send()
}
}
}
class ViewController1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let combinedObject = CombinedObject(vc: self, index: 0)
let view1 = View1<ViewController1>().environmentObject(combinedObject)
let hostingController = UIHostingController(rootView: view1)
self.addChild(hostingController)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(hostingController.view)
hostingController.didMove(toParent: self)
}
}
struct View1<VC1: UIViewController>: View {
@EnvironmentObject var combinedObject: CombinedObject<VC1>
var body: some View {
VStack() {
Button(action: {
self.combinedObject.interactor.buttonClicked()
}, label: {
Text(self.combinedObject.viewModel.text)
})
}
}
}
导入快捷界面
进口联合收割机
类ViewModel1:ObservableObject{
//已发布数据以供查看
@已发布的变量文本:字符串
初始化(文本:字符串){
self.text=文本
}
}
类Interactor1:ObservableObject{
让vc:vc
是否让viewModel:ViewModel1?
init(vc:vc,viewModel:ViewModel1?){
self.vc=vc
self.viewModel=viewModel
}
func按钮单击(){
//使用vc显示第二个ViewController。显示。。。
}
}
类组合对象:ObserveObject{
@已发布的变量交互器:交互器1
@已发布的var viewModel:ViewModel1
var anycancelable:anycancelable?=nil
var ANYCANCELABLE2:ANYCANCELABLE?=nil
init(vc:vc,索引:Int){
viewModel=ViewModel1(文本:“text1”)
interactor=Interactor1(vc:vc,viewModel:nil)
interactor=Interactor1(vc:vc,viewModel:viewModel)
AnyCancelable=Interactior.objectWillChange.sink{(\u1)in
self.objectWillChange.send()
}
AnyCancelable2=viewModel.objectWillChange.sink{(\u1)in
self.objectWillChange.send()
}
}
}
类ViewController1:UIViewController{
重写func viewDidLoad(){
super.viewDidLoad()
让combinedObject=combinedObject(vc:self,索引:0)
让view1=view1().environmentObject(组合对象)
让hostingController=UIHostingController(rootView:view1)
self.addChild(主机控制器)
hostingController.view.translatesAutoresizingMaskIntoConstraints=false
self.view.addSubview(hostingController.view)
hostingController.didMove(toParent:self)
}
}
结构视图1:视图{
@环境对象变量combinedObject:combinedObject
var body:一些观点{
VStack(){
按钮(操作:{
self.combinedObject.interactior.buttonClicked()
},标签:{
文本(self.combinedObject.viewModel.Text)
})
}
}
}
环境对象是按类型注入的,因此您可以分别注入视图模型和交互对象,如下所示
struct View1<VC1: UIViewController>: View {
@EnvironmentObject var viewModel: ViewModel1
@EnvironmentObject var iterator: Interactor1<VC1>
...
顺序并不重要,因为是按类型注入的
使用Xcode 11.2/iOS 13.2进行测试,这意味着我将在显示根视图之前加载所有屏幕的数据。也许这是不可能做到我试图实现的,但这种方式至少不能真正很好地工作,因为它是昂贵的,没有必要加载很多甚至可能不需要的数据(对于不想访问所有视图的用户)。视图可能会在需要时调用某些方法来设置环境数据?无论如何,我只是对如何在不使用vc部件的情况下很好地设置体系结构有点困惑。@DevB2F,等等。。。在组合对象中你没有做同样的事情吗?我以为你只是想分开。。。而且,这只是一种设置环境的机制,您不必一次加载所有内容,有些内容可以是惰性的,有些内容可以是最近注入的,有些内容可以是可计算的,等等。这只是一种在层次结构中的任何地方都可以设置引用的可能性。其他一切都在你的控制之下。
struct SubView1<VC1: UIViewController>: View { // only with view model
@EnvironmentObject var viewModel: ViewModel1
struct SubView2<VC1: UIViewController>: View { // only with iterator
@EnvironmentObject var iterator: Interactor1<VC1>
View1(...)
.environmentObject(ViewModel1(...))
.environmentObject(Interactor1(...))