前一篇第 13 天是提到「EnvironmentObject」,雖然本系列文章基本上沒有前後關聯,如果你是還沒讀過前一篇的讀者,也推薦你去讀讀。
從 iOS 15 開始, Apple 的 SwiftUI 開始提供 refreshable
這個 modifier ,大家念念在望的功能終於可以用 SwiftUI 的方式實作了。
先來看今天最後要做出來的畫面。
下拉之後可以在清單的前面加上 3 行,並有重置按鈕可以重置回初始狀態。
非常簡單,只要加上這個 modifier 即可!也沒有像 UIKit 需要較多的步驟。也沒有被限制誰先可以用誰先不能用的情形。
ScrollView {
// 你的內容
}
.refreshable {}
我們做一個這樣子的 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
}
}
像是這樣,在 ScrollView 後面加上 refreshable ,內部則呼叫模擬網路存取的 reload
方法。
ScrollView {
// 省略
}
// 加上 refreshable ,呼叫模擬網路存取的 `reload` 方法
.refreshable {
do {
try await reload()
} catch {
print("Error: \(error)")
}
}
refreshable 的 indicator 會根據 await 執行的結果而結束顯示,不用項 UIRefreshControl 那樣,像下面的程式碼那樣需要我們去停止它,非常方便。
refreshControl.endRefreshing()
到這裡就是在 SwiftUI 中如何使用 EnvironmentObject 。
那今天的 SwiftUI 的大大小小就到這邊,以上,明天見!
本篇使用到的 UI 元件和 modifiers 基本上沒有受到版本更新影響
因此 Xcode 14 等環境下使用也是沒問題的。