[本文翻译自hackingwithswift,点击链接阅读原文]
到目前为止,我们允许用户浏览菜单,在订单中添加项目,然后查看他们的总订单。我们没有做的是创建一个机制来确认该订单,所以这是我们的下一项工作。
虽然这实际上不会将任何东西发送到某处的服务器,但我至少想利用这个机会展示SwiftUI最令人印象深刻的功能之一:表单。
表单是像堆栈一样的容器,但它们是专门为设置屏幕和用户输入等内容设计的——用户可能想在一个地方做出几个选择的任何地方。正如您将看到的,表单会做一些有趣的事情,一路走来,我将向您展示如何使用常见的UI控件,如选择器、文本字段、分段控件等。
现在我知道你在想什么了:文本字段肯定很简单?嗯,它们并不难,但它们也不像你习惯的UIKit那样工作。
为了启动并运行,让我们创建一个新的CheckoutView
结构,我们将在按下Place Order时显示该结构。按Cmd+N添加一个新的SwiftUI视图,称为“CheckoutView”,然后给它其他视图相同的@EnvironmentObject
属性:
@EnvironmentObject var order: Order
确保在视图的预览中也提供:
struct CheckoutView_Previews: PreviewProvider {
static var previews: some View {
CheckoutView().environmentObject(Order())
}
}
这是简单的东西,所以让我们尝试一些新的东西:让我们展示一个具有各种付款选项的选择器,允许用户选择现金、信用卡或iDine积分。
这需要两个新属性。首先,我们需要一个属性,列出我们想在选择器中显示的所有可能值——现在添加这个:
let paymentTypes = ["Cash", "Credit Card", "iDine Points"]
其次,我们需要一个属性,SwiftUI可以存储在选择器中选择的值。你看,当我们的用户界面更改时,SwiftUI想知道它,以便它可以更新我们的视图——例如,也许现在会显示一些隐藏的视图。我们不是要求手动观看更改,而是将选择器绑定到结构上的属性上,这样当选择器更改时,SwiftUI也会自动更改属性。而且,就像环境对象一样,这将导致SwiftUI重新调用我们的body
属性,以便任何更改都可见。
我们已经使用@EnvironmentObject
来处理来自外部来源的数据。然而,在这里,这些数据仅用于我们的视图,并且将是一个简单的值,而不是符合ObservableObject
的专用类。
SwiftUI为我们提供了这些简单的本地值的不同属性包装器:@State
。它的工作方式与@EnvironmentObject
相似,因为如果对象发生变化,它会自动刷新我们的用户界面,但它是为整数和字符串等简单的本地值而设计的——如果你想使用像Order
这样的类,你需要使用其他东西。
重要提示:如果您想使用仅由当前视图使用的简单值,您应该将@State
用于您的属性包装器。苹果还建议您将这些属性标记为private
,以重申它们不是为外部访问而设计的。
立即将此属性添加到CheckoutView
中:
@State private var paymentType = "Cash"
现在让我们用选择器填写body
属性。这都是新的,所以我会先给你代码,然后再说一遍它的作用:
VStack {
Section {
Picker("How do you want to pay?", selection: $paymentType) {
ForEach(paymentTypes, id: \.self) {
Text($0)
}
}
}
}
.navigationTitle("Payment")
.navigationBarTitleDisplayMode(.inline)
让我们来分解一下:
我们有一个包含一个部分的垂直堆栈。
该部分包含一个选择器,该选择器使用
$paymentType
进行选择。它有一个标签还不可见,但一会儿就会改变。
在选择器中,我们循环所有付款类型,并将它们添加为选项。
屏幕上的标题是小文本“付款”,而不是大标题。
当然,真正的问题是:为什么$paymentType
而不是paymentType
?
评论区