建立第一個 SwiftUI App:Day 10 – ActionSheet

Photo by Toa Heftiba on Unsplash
Photo by Toa Heftiba on Unsplash
上一章中我們完成了菜單的畫面,本章會加入點餐的動作。我們會介紹如何使用 ActionSheet 這個 UI 元件。此外,還會介紹如何在 Swift 使用 Singleton 物件。這是常常使用的技巧。

上一章中我們完成了菜單的畫面,本章會加入點餐的動作。我們會介紹如何使用 ActionSheet 這個 UI 元件。此外,還會介紹如何在 Swift 使用 Singleton 物件。這是常常使用的技巧。

Coffee Shop 的完整程式碼可以在 下載。

加入 ActionSheet

點餐的動作是,點擊商品列,會顯示 ActionSheet,詢問是否要將此商品加入到帳單。畫面如下:

菜單 ActionSheet
菜單 ActionSheet

所以首先我們要加上 ActionSheet。回到 MenuRowView,新增下方的程式碼到 Button

Button 呼叫 .actionSheet(isPresetned:),如果 showingActionSheettrue 的話,就會顯示裡面的 ActionSheet

ActionSheet 的第一個參數標題。第二參數是按鈕。第一個按鈕是可自訂動作的按鈕。第二個按鈕是預設的 Destructive 按鈕,它會顯示紅色的字,而且沒有任何動作。當你點擊任一個按鈕後,showingActionSheet 會自動被設為 false

struct MenuRowView: View {
    ...
    @State var showingActionSheet = false

    var body: some View {
        Button(action: {
            self.showingActionSheet = true
        }) {
            ...
        }
            ...
            .actionSheet(isPresented: self.$showingActionSheet) {
                ActionSheet(title: Text(product.name ?? ""), buttons: [
                    .default(Text("Add")) {
                        OrderManager.shared.add(product: self.product)
                    },
                    .destructive(Text("Cancel")),
                ])
            }
            ...
    }
}

訂單管理

剛剛的第一個按鈕中,我們會將商品加入一個叫 OrderManager 的物件中,他會紀錄所有被點的商品。

在 Model 資料夾下新增 OrderManagerOrder,程式碼如下方。OrderManager 會管理數筆訂單。而 Order 代表一筆訂單,它紀錄著商品的資訊和數量。OrderManager 提供 add(product:) 方法可以加入商品。如果商品的訂單已經存在,則增加數量。

我們希望 OrderManager 在整個 App 裡面只有一個實體,以便於管理,這也叫做 Singleton。它是用來管理訂單,所以不需要多於一個實體。因此,我們宣告一個靜態的 Property 叫 shared。整個程式都會透過 shared 來存取這個唯一的 OrderManager

class OrderManager {
    static let shared = OrderManager()

    var orders: [Order] = []

    func add(product: Product) {
        guard let id = product.id else {
            return
        }

        if let index = orders.firstIndex(where: { $0.id == id }) {
            orders[index] = orders[index].increased()
        } else {
            let order = Order(id: id, name: product.name ?? "", price: product.price, quantity: 1)
            orders.append(order)
        }
    }
}
struct Order {
    let id: UUID
    let name: String
    let price: Double

    var quantity: Int
    
    func increased() -> Order {
        var copy = self
        copy.quantity += 1
        return copy
    }
}

結語

SwiftUI 將 Button 整合了 ActionSheet,使它們變為更為好用。在 UIKit 中,這兩個元件是完全獨立的,所以在使用上也就沒有這麼地方便。另外,我們還介紹了 Singleton 的使用方式。我們常常會建立一些 class,而且希望整個 App 中只會有那一個實體。這時候我們就會用 Singleton 來實作。在 Swift 中,Singleton 的物件常常會用 shared、default、instance 等這幾個來作為靜態變數的名稱。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

You May Also Like
Photo by Alex Alvarez on Unsplash
Read More

Dispatch Queue 教學

GCD 提供有效率的並行處理,讓我們不需要直接管理多執行緒。它的 Dispatch Queues 可以循序地(serially)或是並行地(concurrently)執行任務。我們只需要將要並行的程式當作任務提交到 dispatch queues 就可以了。
Read More
Photo by Florinel Gorgan on Unsplash
Read More

如何製作一個 XCFramework

XCFramework 讓你可以將 iPhone、iPhone 模擬器等多的不同平台的二進位碼打包到一個可發佈的 .xcframework 檔。你只需要為你的 Framework 產生出一個 .xcframework 檔,就可以支援多種平台。
Read More
Photo by Fabian Gieske on Unsplash
Read More

SwiftUI @State & @Binding 教學

SwiftUI 推出了兩個 Property Wrapper – @State and @Binding。利用它們可以達到變數的 Two-way Binding 功能。也就是當變數的值改變時,它會重新被顯示。本章藉由製作一個 Custom View 來展示如何使用 @State 和 @Binding。
Read More
Photo by Svitlana on Unsplash
Read More

iOS:禁止螢幕截圖

基於一些理由,我們可能會想要禁止使用者對我們的 app 做螢幕截圖。然而,iOS 並沒有提供這樣的功能。所幸,我們可以利用 UITextField 來達到此效果。
Read More