51: CupcakeCorner, part 3

그루두·2024년 6월 25일
0

100 days of SwiftUI

목록 보기
58/108

100 days of swiftui: 51

@Bindable

CupcakeCorner 앱의 경우 한 주문에서 주문시키는 상품과 주소를 입력한다. 그래서 하나의 @Observable인 Order 인스턴스를 활용한다.

이때 OrderView, AddressView에서 하나의 인스턴스를 가지고(@State를 통해 새 인스턴스를 만들지 않으면서) 화면에 변화를 나타내기 위해 @Bindable을 사용하면 된다.

struct AddressView: View {
    @Bindable var order: Order
    var body: some View {
        Form {
        // ...

깃헙 링크

AddressView에서 내용을 입력하는 대로 바로 화면에 나타나고, OrderView로 이동하였다가 돌아와도 저장되어 있는 것을 확인할 수 있다.

CheckoutView 설정

주문의 세부 선택에 따라 cost를 설정하고 이를 나타내는 CheckoutView를 설정했다.

💡 ScrollView가 휴대폰의 세로 길이보다 길지 않으면 Scroll이 되지 않게 하기 위해서 .scrollBounceBehavior(.basedOnSize)를 설정했다.


깃헙 링크

주문 정보 주고 받기

사용자가 주문하기 버튼을 클릭하면 특정 url에 주문 정보를 encode해서 보내고, 이 주문에 대해 문제가 없으면 data를 받아 deconde할 수 있다.

    func placeOrder() async {
        guard let encoded = try? JSONEncoder().encode(order) else {
            print("Error: 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"
        do {
            let (data, _) = try await URLSession.shared.upload(for: request, from: encoded)
            let decodedOrder = try JSONDecoder().decode(Order.self, from: data)
            confirmationMessage = "Your order for \(decodedOrder.quantity) x \(Order.types[decodedOrder.type].lowercased()) cupcakes is on its way!"
            showingConfirmation = true
        } catch {
            print("Error: Get \(error.localizedDescription)")
            return
        }
    }

깃헙 링크

static으로 설정한 typesOrder.types로 사용해야 한다. 그리고 placeOrder()는 async 함수이기 때문에 즉각적으로 함수를 실행하고 기다리지 않는 버튼에서는 다음 설정이 필요하다.

                Button("Place Order") {
                    Task {
                        await placeOrder()
                    }
                }

이렇게 컵케이크 주문을 실행해보고 encode된 data를 살펴보면 아래와 같다.

💡 xcode에서 let url = URL(string: "https://reqres.in/api/cupcakes")! 이 코드 줄에 breakpoint를 찍고 시뮬레이터 실행이 멈추면, 터미널에 p String(decoding: encoded, as: UTF8.self)를 입력하면 확인할 수 있다.

data의 이름이 내가 설정한 이름에 _가 붙어있는 것을 확인할 수 있다. 마찬가지로 @Observable인 class의 매크로 때문인데, CodingKey로 미리 지정하면 이를 방지할 수 있다.

    enum CodingKeys: String, CodingKey {
        case _type = "type"
        case _quantity = "quantity"
        case _specialRequestEnabled = "specialRequestEnabled"
        case _extraFrosting = "extraFrosting"
        case _addSprinkles = "addSprinkles"
        case _name = "name"
        case _streetAddress = "streetAddress"
        case _city = "city"
        case _zip = "zip"
    }

깃헙 링크

💡 다른 값에 따라 설정되거나 static인 속성 types, hasValidAddress, cost를 Codingkeys에 설정하면 Order가 Codable 프로토콜을 준수하지 못하는 에러가 발생한다.

결과물

profile
계속 해보자

0개의 댓글

관련 채용 정보