100 Days of SwiftUI(DAY 51(Project10 part 3))

ObservableObjectクラスのエンコード
Encoding an ObservableObject class
@Publishedクラスのプロパティにはプロパティラッパーを使用する必要があり、その直後に自動Codable適合性のサポートが失われました。
Swiftは公開されたプロパティをエンコードおよびデコードする方法を理解していないため、ビルドは失敗します。これは問題です。ユーザーの注文をインターネットサーバーに送信するためです。つまり、JSONとして必要Codableです。つまり、プロトコルが機能する必要があります。

ここでの修正はCodable、手動で準拠を追加することです。
列挙型をOrder追加します。

CodingKey
encode
decode

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")
        }
    }
}

インターネットを介した注文の送受信
Sending and receiving orders over the internet

iOSには、ネットワーキングを処理するための素晴らしい機能がいくつかあり、特にこのURLSessionクラスを使用すると、データの送受信が驚くほど簡単になります。これと組み合わせて、CodableSwiftオブジェクトをJSONに変換したり、JSONから変換したりして、URLRequestデータの送信方法を正確に構成できるようにすると、約20行のコードですばらしいことを実現できます。

現在のorderオブジェクトを送信可能なJSONデータに変換します。
URLRequestエンコードされたデータをJSONとして送信するようにを準備します。
その要求を実行し、応答を処理します。

import SwiftUI

struct CheckoutView: View {
    @ObservedObject var order: Order
    
    @State private var confirmationMessage = ""
    @State private var showingConfirmation = false
    
    func placeOrder() {
        guard let encoded = try? JSONEncoder().encode(order) else {
            print("Failed to encode order")
            return
        }
        
        let url = URL(string: "https://reqres.in/api/cupcakes")!
        var request = URLRequest(url: url)
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = encoded
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            // handle the result here.
            guard let data = data else {
                       print("No data in response: \(error?.localizedDescription ?? "Unknown error").")
                       return
                   }
            if let decodedOrder = try? JSONDecoder().decode(Order.self, from: data) {
                self.confirmationMessage = "Your order for \(decodedOrder.quantity)x \(Order.types[decodedOrder.type].lowercased()) cupcakes is on its way!"
                self.showingConfirmation = true
            } else {
                print("Invalid response from server")
            }
        }.resume()
    }
    

    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") {
                        self.placeOrder()
                    }
                    .padding()
                }
            }
        }
        .navigationBarTitle("Check out", displayMode: .inline)
        .alert(isPresented: $showingConfirmation) {
            Alert(title: Text("Thank you!"), message: Text(confirmationMessage), dismissButton: .default(Text("OK")))
        }
    }
}

先に進む前に最後に1つありDispatchQueue.main.async()ます。このプロジェクトでは、作業をメインスレッドにプッシュバックしていました。これは、AppleのGrand Central Dispatchフレームワークの一部です。これは、複数のスレッドで作業を実行するための大きくて強力なフレームワークです。詳細についてはここで説明しませんが、すでに他の場所で詳しく説明しています。詳細については、Hacking with Swiftのクラシック版のプロジェクト9を参照してください。
GCDを使用して複雑なタスクをバックグラウンドで実行する方法を学びます。
AppleのGrand Central Dispatchフレームワーク

SwiftUIで非同期で画像を表示する方法
↑の関連リンク YOUTUBE

検索キーワード
Downloading Images in SwiftUI