从日期选择器获取和设置日期,但仍然获取旧的默认值

kar*_*ngh 4 swiftui

我想从 获取并设置日期DatePicker,但我的日期没有更新。SwiftUI 对我来说是新的,我对使用什么类型的属性包装器感到困惑。请帮忙提供建议,并建议何时何地使用@State,我读了一些文章@Binding@Published但我仍然不清楚概念。

这里我使用了 MVVM 和 SwiftUI,我的代码如下。

class MyViewModel:ObservableObject {
    @Published var selectedDate : Date = Date()
    @Published var selectedDateStr : String = Date().convertDateToString(date: Date())

}

struct DatePickerView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @ObservedObject var viewModel : MyViewModel

    var dateFormatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateStyle = .long
        return formatter
    }

    @State private var selectedDate = Date()

    var body: some View {
        VStack {
            //Title
            HStack{
            Text("SELECT A DATE")
                .foregroundColor(.white)
                .font(.system(size: 20))
            }
                .frame(width:UIScreen.main.bounds.width,height: 60)
            .background(Color.red)

            //Date Picker
            DatePicker(selection: $selectedDate, in: Date()-15...Date(), displayedComponents: .date) {
                Text("")
            }.padding(30)

            Text("Date is \(selectedDate, formatter: dateFormatter)")
            Spacer()

            //Bottom buttons

                Text("DONE")
                    .fontWeight(.semibold)
                    .frame(width:UIScreen.main.bounds.width/2,height: 60)
                    .onTapGesture {
                        self.viewModel.selectedDate = self.selectedDate
                        self.presentationMode.wrappedValue.dismiss()

                }
        }
    }
}

//calling:

DatePickerView(viewModel: self.viewModel)

Run Code Online (Sandbox Code Playgroud)

Nid*_*dhi 5

回答关于 SwiftUI 中使用的包装器属性的第二个问题,即 @State、@Binding、@Published。

\n\n

SwiftUI 中最常见的\xc2\xa0@Things\xc2\xa0 是:

\n\n
\xe2\x80\xa2   @State\xc2\xa0-\xc2\xa0Binding<Value>\n\xe2\x80\xa2   @Binding\xc2\xa0-\xc2\xa0Binding<Value>\n\xe2\x80\xa2   @ObservedObject\xc2\xa0-\xc2\xa0Binding<Value>\xc2\xa0(*)\n\xe2\x80\xa2   @EnvironmentObject\xc2\xa0-\xc2\xa0Binding<Value>\xc2\xa0(*)\n\xe2\x80\xa2   @Published\xc2\xa0-\xc2\xa0Publisher<Value, Never>\n
Run Code Online (Sandbox Code Playgroud)\n\n

(*) 从技术上讲,我们得到一个 \xc2\xa0Wrapper 类型的中间值,一旦我们将 keyPath 指定为对象内的实际值,它就会变成 \xc2\xa0Binding\xc2\xa0。\n因此,如您所见,大多数SwiftUI 中的属性包装器,即负责 view\xe2\x80\x99s 状态的属性,正在 \xe2\x80\x9cprojected\xe2\x80\x9d as\xc2\xa0Binding,用于在视图之间传递状态.\n唯一与常见过程不同的包装器是\xc2\xa0@Published,但是:\n 1. 它\xe2\x80\x99 是在Combine 框架中声明的,而不是在SwiftUI 中\n 2. 它有不同的用途:使值\xc2\xa0observable\n 3.它从未用于视图\xe2\x80\x99s变量声明,仅在\xc2\xa0ObservableObject内部\n考虑SwiftUI中的这种非常常见的场景,我们在其中声明\xc2\xa0ObservableObject \xc2\xa0 并将其与视图中的 \xc2\xa0@ObservedObject\xc2\xa0 属性一起使用:

\n\n
class ViewModel: ObservableObject {\n    @Published var value: Int = 0\n}\n\nstruct MyView: View {\n    @ObservedObject var viewModel = ViewModel()\n\n    var body: some View { ... }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

MyView\xc2\xa0可以参考\xc2\xa0$viewModel.value\xc2\xa0和\xc2\xa0viewModel.$value\xc2\xa0 - 两个表达式都是正确的。很混乱,\xe2\x80\x99不是吗?\n这两个表达式最终代表不同类型的值:\xc2\xa0Binding\xc2\xa0和\xc2\xa0Publisher,分别。\n两者都有实际用途:

\n\n
var body: some View {\n    OtherView(binding: $viewModel.value)     // Binding\n        .onReceive(viewModel.$value) { value // Publisher\n            // do something that does not\n            // require the view update\n        }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

希望它可以帮助你。

\n