このプロジェクトの最初のステップは、注文の基本的な詳細(注文するカップケーキの数、注文する種類、特別なカスタマイズがあるかどうか)を示す注文画面を作成することです。
以前は@State、単純な値の型と@ObservedObject参照の型に使用しており、ObservableObject構造体を含むクラスを作成して、両方の利点を得る方法を見てきました。
ここでは、別のソリューションを使用します。画面間で渡されるすべてのデータを格納する単一のクラスを作成します。これは、アプリのすべての画面が同じデータを共有することを意味します。
didSetプロパティオブザーバー
import SwiftUI class Order: ObservableObject { static let types = ["Vanilla", "Strawberry", "Chocolate", "Rainbow"] @Published var type = 0 @Published var quantity = 3 //@Published var specialRequestEnabled = false @Published var specialRequestEnabled = false { didSet { if specialRequestEnabled == false { extraFrosting = false addSprinkles = false } } } @Published var extraFrosting = false @Published var addSprinkles = false }
import SwiftUI struct ContentView: View { @ObservedObject var order = Order() var body: some View { NavigationView { Form { Section { Picker("Select your cake type", selection: $order.type) { //ForEach(0..<Order.types.count) { ForEach(0..<Order.types.count, id: \.self) { Text(Order.types[$0]) } } Stepper(value: $order.quantity, in: 3...20) { Text("Number of cakes: \(order.quantity)") } } Section { Toggle(isOn: $order.specialRequestEnabled.animation()) { Text("Any special requests?") } if order.specialRequestEnabled { Toggle(isOn: $order.extraFrosting) { Text("Add extra frosting") } Toggle(isOn: $order.addSprinkles) { Text("Add extra sprinkles") } } } Section { NavigationLink(destination: AddressView(order: order)) { Text("Delivery details") } } } .navigationBarTitle("Cupcake Corner") } } }
import SwiftUI struct AddressView: View { @ObservedObject var order: Order var body: some View { Text("Hello World") } } struct AddressView_Previews: PreviewProvider { static var previews: some View { AddressView(order: Order()) } }
有効な住所を確認する
Checking for a valid address
import SwiftUI class Order: ObservableObject { static let types = ["Vanilla", "Strawberry", "Chocolate", "Rainbow"] @Published var type = 0 @Published var quantity = 3 //@Published var specialRequestEnabled = false @Published var specialRequestEnabled = false { didSet { if specialRequestEnabled == false { extraFrosting = false addSprinkles = false } } } @Published var extraFrosting = false @Published var addSprinkles = false //-------------------------------- @Published var name = "" @Published var streetAddress = "" @Published var city = "" @Published var zip = "" var hasValidAddress: Bool { if name.isEmpty || streetAddress.isEmpty || city.isEmpty || zip.isEmpty { return false } return true } }
import SwiftUI struct AddressView: View { @ObservedObject var order: Order var body: some View { Form { Section { TextField("Name", text: $order.name) TextField("Street Address", text: $order.streetAddress) TextField("City", text: $order.city) TextField("Zip", text: $order.zip) } Section { NavigationLink(destination: CheckoutView(order: order)) { Text("Check out") } } .disabled(order.hasValidAddress == false) } .navigationBarTitle("Delivery details", displayMode: .inline) } } struct AddressView_Previews: PreviewProvider { static var previews: some View { AddressView(order: Order()) } }
import SwiftUI struct CheckoutView: View { @ObservedObject var order: Order var body: some View { Text("Hello, World!") } } struct CheckoutView_Previews: PreviewProvider { static var previews: some View { CheckoutView(order: Order()) } }
import SwiftUI struct ContentView: View { @ObservedObject var order = Order() var body: some View { NavigationView { Form { Section { Picker("Select your cake type", selection: $order.type) { //ForEach(0..<Order.types.count) { ForEach(0..<Order.types.count, id: \.self) { Text(Order.types[$0]) } } Stepper(value: $order.quantity, in: 3...20) { Text("Number of cakes: \(order.quantity)") } } Section { Toggle(isOn: $order.specialRequestEnabled.animation()) { Text("Any special requests?") } if order.specialRequestEnabled { Toggle(isOn: $order.extraFrosting) { Text("Add extra frosting") } Toggle(isOn: $order.addSprinkles) { Text("Add extra sprinkles") } } } Section { NavigationLink(destination: AddressView(order: order)) { Text("Delivery details") } } } .navigationBarTitle("Cupcake Corner") } } }
CheckoutView
OrderクラスをJSON にエンコードし、インターネット経由で送信して、応答を取得する
チェックアウトの準備
Preparing for checkout
import SwiftUI class Order: ObservableObject { static let types = ["Vanilla", "Strawberry", "Chocolate", "Rainbow"] @Published var type = 0 @Published var quantity = 3 //@Published var specialRequestEnabled = false @Published var specialRequestEnabled = false { didSet { if specialRequestEnabled == false { extraFrosting = false addSprinkles = false } } } @Published var extraFrosting = false @Published var addSprinkles = false //-------------------------------- @Published var name = "" @Published var streetAddress = "" @Published var city = "" @Published var zip = "" var hasValidAddress: Bool { if name.isEmpty || streetAddress.isEmpty || city.isEmpty || zip.isEmpty { return false } return true } var cost: Double { // $2 per cake var cost = Double(quantity) * 2 // complicated cakes cost more cost += (Double(type) / 2) // $1/cake for extra frosting if extraFrosting { cost += Double(quantity) } // $0.50/cake for sprinkles if addSprinkles { cost += Double(quantity) / 2 } return cost } }
import SwiftUI struct CheckoutView: View { @ObservedObject var order: Order var body: some View { GeometryReader { geo in ScrollView { VStack { Image("cupcakes") .resizable() .scaledToFit() .frame(width: geo.size.width) Text("Your total is $\(self.order.cost, specifier: "%.2f")") .font(.title) Button("Place Order") { // place the order } .padding() } } } .navigationBarTitle("Check out", displayMode: .inline) } }