iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Mobile Development

SwiftUI 的大大小小系列 第 14

Day 14 - 在 SwiftUI 中為 Scroll View 加入下拉更新

  • 分享至 

  • xImage
  •  

hero

前一篇第 13 天是提到「EnvironmentObject」,雖然本系列文章基本上沒有前後關聯,如果你是還沒讀過前一篇的讀者,也推薦你去讀讀。

下拉更新 - refreshable

從 iOS 15 開始, Apple 的 SwiftUI 開始提供 refreshable 這個 modifier ,大家念念在望的功能終於可以用 SwiftUI 的方式實作了。

今天要做的東西

先來看今天最後要做出來的畫面。

1401.gif

下拉之後可以在清單的前面加上 3 行,並有重置按鈕可以重置回初始狀態。

使用方法

非常簡單,只要加上這個 modifier 即可!也沒有像 UIKit 需要較多的步驟。也沒有被限制誰先可以用誰先不能用的情形。

ScrollView {
    // 你的內容
}
.refreshable {}

動手做做看

0402

我們做一個這樣子的 UI

struct ContentView: View {
    @State private var items = [1, 2, 3]
    var body: some View {
        ScrollView {
            navigation()
            ForEach(items, id: \.self) { day in
                HStack {
                    Text("Day: \(day)")
                    Spacer()
                }
                .padding()
                .background(
                    RoundedRectangle(cornerRadius: 5)
                        .stroke()
                        .foregroundColor(.gray)
                )
                .padding(.horizontal, 8)
            }
        }
    }
    
    func navigation() -> some View {
        HStack {
            Text("鐵人賽文章")
                .fontWeight(.bold)
            Spacer()
            Text("總篇數 \(items.count)")
            Divider()
            Button {
                reset()
            } label: {
                Text("重置")
            }
        }
        .padding()
    }
    
    private func reset() {
        items = [1, 2, 3]
    }

    /// 利用 async-await 模擬網路存取,內部做了
    /// 1. 延時 1 秒
    /// 2. 在 items 前面加上三個新的數字
    private func reload() async throws {
        let second: UInt64 = 1_000_000_000
        try await Task.sleep(nanoseconds: second)
        let count = items.count
        items = [count + 1, count + 2, count + 3] + items
    }
}

加上 refreshable

像是這樣,在 ScrollView 後面加上 refreshable ,內部則呼叫模擬網路存取的 reload 方法。

ScrollView {
    // 省略
}
// 加上 refreshable ,呼叫模擬網路存取的 `reload` 方法
.refreshable {
    do {
        try await reload()
    } catch {
        print("Error: \(error)")
    }
}

refreshable 的 indicator 會根據 await 執行的結果而結束顯示,不用項 UIRefreshControl 那樣,像下面的程式碼那樣需要我們去停止它,非常方便。

refreshControl.endRefreshing()

成果

1401.gif

結語

到這裡就是在 SwiftUI 中如何使用 EnvironmentObject 。

那今天的 SwiftUI 的大大小小就到這邊,以上,明天見!

環境

  • Xcode 15 beta 8

本篇使用到的 UI 元件和 modifiers 基本上沒有受到版本更新影響

因此 Xcode 14 等環境下使用也是沒問題的。


上一篇
Day 13 - 在 SwiftUI 中利用 EnvironmentObject 進行 Dependency Injection
下一篇
Day 15 - 在 SwiftUI 中建立 TabView
系列文
SwiftUI 的大大小小30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言