首页 > 解决方案 > SwiftUI MVVM 绑定

问题描述

如何将 a 传递给@BindingViewModel。

让我们考虑一个简单的例子,

struct TopView: View {
    @State var isPresented: Bool
    var body: some View {
        SubView(isPresented: $isPresented)
    }
}

struct SubView: View {
    @Binding var isPresented: Bool
}

然后,如果我们想要一个 MVVM 模式,

@Binding在中使用安全ObservableObject吗?

例如,写作是否安全,

struct TopView: View {
    @State var isPresented: Bool
    var body: some View {
        SubView(model: SubViewModel(isPresented: $isPresented))
    }
}

struct SubView: View {
    @ObservedObject var model: SubViewModel
}


// In "SubViewModel.swift"

import Foundation
import Combine
import SwiftUI

public final class SubViewModel: ObservedObject {
    @Binding var isPresented: Bool
    
    public init(isPresented: Binding<Bool>) {
        self._isPresented = isPresented
    }
}

你会怎么做?类似的包括如何将 environmentObject 传递给视图模型?

标签: swiftui

解决方案


您正在描述ObservableObject. @Binding并且@State仅用于View

Apple SwiftUI 教程可能对您了解 SwiftUI 概念很有帮助。https://developer.apple.com/tutorials/swiftui/

您的代码中有一些基本错误我在下面的代码中提到了更改。

import SwiftUI

struct PassingBinding: View {
    var body: some View {
        TopView1()//Best Practice
        //TopView2()//Singleton Pattern
    }
}
///This is the best way to do it
///https://developer.apple.com/tutorials/swiftui/handling-user-input
struct TopView1: View {
    @StateObject var model: SubViewModel = SubViewModel()
    var body: some View {
        VStack{
            SubView1().environmentObject(model)
            
            Button(action: {
                self.model.isPresented.toggle()
            }, label: {
                Text("Toggle isPresented")
            })
        }
    }
}

struct SubView1: View {
    @EnvironmentObject var model: SubViewModel
    var body: some View {
        Text("SubView - isPresented == \(model.isPresented.description)")
    }
}
///Another way that has some specifc uses is to use a Singleton model
///https://developer.apple.com/documentation/swift/cocoa_design_patterns/managing_a_shared_resource_using_a_singleton
struct TopView2: View {
    @StateObject var model: SubViewModel = SubViewModel.shared
    var body: some View {
        VStack{
            SubView2()
            
            Button(action: {
                self.model.isPresented.toggle()
            }, label: {
                Text("Toggle isPresented")
            })
        }        }
}

struct SubView2: View {
    @StateObject var model: SubViewModel = SubViewModel.shared
    var body: some View {
        Text("SubView - isPresented ==  \(model.isPresented.description)")
    }
}

///This item can be Observed "ObservableObject" vs I am Observing this object "ObservedObject"
///https://developer.apple.com/documentation/combine/observableobject
public final class SubViewModel: ObservableObject {
    static let shared: SubViewModel = SubViewModel()//Singleton Pattern 
    
    @Published var isPresented: Bool = false //Initialize here this is the source for the View
    //@Binding and @State is are only used in View struct not in an ObservableObject.https://developer.apple.com/documentation/swiftui/binding
    
    
}
struct PassingBinding_Previews: PreviewProvider {
    static var previews: some View {
        PassingBinding()
    }
}

推荐阅读