Discover Observation in SwiftUI

更新於 發佈於 閱讀時間約 8 分鐘


New Zealand — Queenstown

New Zealand — Queenstown

What is Observation?


Observation 是 Swift 中用於追蹤屬性變化的新功能,透過 macro 對它們進行轉換。在 SwiftUI 裡針對特別的 property 發生變化時,才重新計算 View 的 body。

要使用非常簡單,加上 @Observable 即可,這就是依靠 macro 強大的力量,而且就不用使用 Property wrapper 了,例如 @State@Published

@Observable class FoodTruckModel {    

var orders: [Order] = []

var donuts = Donut.all

}

接下來介紹一個範例,在這個 var body: some View { ... 裡,只有用到 model.donuts 所以假設我們按下 Button ,整個 View 是會更新的。

但假設現在 Button 的功能,換成新增一個 order,但在 View 的 body 裡沒有使用到 orders 的話,整個 View 是不會更新,因為這個 orders 這個 property 是沒有被追蹤的。

raw-image

這種機制是 Observation 的一個重要優勢,它使得 SwiftUI 能夠精確地、選擇性地更新 UI,只重新計算那些真正受到資料變化影響的視圖部分,這能帶來顯著的效能提升。

不像舊的 ObservableObject 和 @Published 可能會導致更廣泛的視圖更新, @Observable 和 SwiftUI 的結合能夠實現更細粒度的更新控制。

那我們現在把它換成 computed property,看看會發生什麼事

我們現在對 FoodTruckModel 在新增一個 computed property, var orderCount: Int { orders.count }

@Observable class FoodTruckModel {
var orders: [Order] = []
var donuts = Donut.all
var orderCount: Int { orders.count }
}

struct DonutMenu: View {
let model: FoodTruckModel

var body: some View {
List {
Section("Donuts") {
ForEach(model.donuts) { donut in
Text(donut.name)
}
Button("Add new donut") {
model.addDonut()
}
}
Section("Orders") {
LabeledContent("Count", value: "\(model.orderCount)")
}
}
}
}

這時候以 View 的角度來看,我們追蹤的是 computed property orderCount,但是裡面訪問到了 orders 這屬性,這也表示 orders 屬性的變化,也會讓 UI 更新。

@Observation

  • Macro
  • Tracks access
  • Property changes cause UI updates

從中我們可以看到這提升了很大的效能

SwiftUI property wrappers


透過 Obserable SwiftUI 的 property wrappers 比以往更簡單, State , Environment , Bindable 變成三種主要與 SwiftUI 一起使用的 property wrappers。

首先介紹 State

使用 @State 修飾的 Model ,它的生命週期會由擁有它的 View 的生命週期來管理,表示與 View 一致。

範例: 在呈現一個 Sheet 時,會使用一個 @State 變數 (donutToAdd) 來綁定數值到可編輯的欄位上。這代表 donutToAdd 這個 Model 是這個 Sheet View 自己的狀態

raw-image


再來 Environment

它是可以全局訪問的值,可以再多個地方共享,像之前用 @EnvironmentObject 一樣,由 super view 傳至 sub view 。

raw-image


最後是 @Bindable

就像之前的 @Binding 一樣,假如這個 Model 是需要雙向綁定的,就是用它,像是要放在 TextField 的情境。

Lightweight

Connect references to UI

Uses $ syntax to create bindings

raw-image


小結

raw-image
  1. 這個 Model 需要成為 View 自身的狀態嗎?(讓 Model 與 View 生命週期一致)
    Yes: @State
    No:
  2. 這個 Model 需要成為 App 全局變數嗎?
    Yes: @Environment
    No:
  3. 這個 Model 只需要綁定嗎?
    Yes: @Bindable
    No:  var

Advanced uses


使用 @Observable 的 Model,在 SwiftUI 上讓 view body 使用,都有自動追蹤 model property 變化而更新 View 的能力。

但也有一些情況需要額外自行處理,如果這個 model 內有一個 computed property 不是由內部 stored property 組成,就需要額外2個步驟。

只有當要觀察的 property 不是透過 Observable 類型的 stored property 組合時,才需要。

這邊就是要手動額外寫

raw-image


Computed properties

  • SwiftUI Tracks access
  • Composed properties
  • Manual control when needed

ObservableObject


假如我們有舊的程式碼,是用 ObservableObject 的,但某天終於可以用 Observable ,我們可以看看如何更新程式碼,使用 Observable 。

範例1

raw-image

非常簡單,刪除 conform ObservableObject 以及 @Published 。

raw-image


在 View 方面

raw-image

也是一樣很簡單,刪除 @ObservedObject ,及 @EnvironmentObject 換成 @Environment

raw-image


所以轉換過程就只有3件事

  1. 換掉 conform ObservableObject ,改用 macro @Observable
  2. 刪除 property wrappers @Published
  3. 只用 @State , @Environment 和 @Bindable

關於從 Observable Object 的 Migrate,可參考官方文件

Resources


留言
avatar-img
留言分享你的想法!
avatar-img
CHENGYANG的沙龍
0會員
7內容數
CHENGYANG的沙龍的其他內容
2025/01/09
觀看 WWDC23 Write Swift macros 筆記 Overview Apple 一開始提出一個範例,把計算的過程顯示成字串,用一個 tuple 組合起來,但這種方式很明顯,有個大缺點,就是容易有人為疏失,導致錯誤發生,還無法用 compiler 檢查字串是否相等於左邊的算數。
Thumbnail
2025/01/09
觀看 WWDC23 Write Swift macros 筆記 Overview Apple 一開始提出一個範例,把計算的過程顯示成字串,用一個 tuple 組合起來,但這種方式很明顯,有個大缺點,就是容易有人為疏失,導致錯誤發生,還無法用 compiler 檢查字串是否相等於左邊的算數。
Thumbnail
2024/12/08
前言 常在寫 leet code 的朋友應該都知道,除了解出題目很重要,還有時間複雜度以及空間複雜度的問題,若能更理解時間複雜度,然後優化解法,就可以讓寫程式的基本底子更上一層樓,以下簡單介紹常見的時間複雜度以及演算法。 除了時間複雜度,也會順便簡單說明相關東西,如下: 相關演算法
Thumbnail
2024/12/08
前言 常在寫 leet code 的朋友應該都知道,除了解出題目很重要,還有時間複雜度以及空間複雜度的問題,若能更理解時間複雜度,然後優化解法,就可以讓寫程式的基本底子更上一層樓,以下簡單介紹常見的時間複雜度以及演算法。 除了時間複雜度,也會順便簡單說明相關東西,如下: 相關演算法
Thumbnail
2024/11/10
Why macros? 最早能從一些 protocol 發現這個特性(Derived protocol conformance),例如 Codable 這樣就可以避免寫重複樣版的程式碼 其實目前在 Swift 中已經有大量的例子,我們開發者只需要寫一些簡單的語法,編譯器就會自動生成一段複
Thumbnail
2024/11/10
Why macros? 最早能從一些 protocol 發現這個特性(Derived protocol conformance),例如 Codable 這樣就可以避免寫重複樣版的程式碼 其實目前在 Swift 中已經有大量的例子,我們開發者只需要寫一些簡單的語法,編譯器就會自動生成一段複
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
本文介紹瞭如何在SwiftUI中調整元件的對齊方式,包括置中、向左/向右/向上/向下對齊的方法。透過調整HStack、VStack以及frame的maxWidth、maxHeight和alignment屬性,可以達到想要的對齊效果。
Thumbnail
本文介紹瞭如何在SwiftUI中調整元件的對齊方式,包括置中、向左/向右/向上/向下對齊的方法。透過調整HStack、VStack以及frame的maxWidth、maxHeight和alignment屬性,可以達到想要的對齊效果。
Thumbnail
這個章節主要介紹了Swift程式語言中物件導向程式設計的基本概念,包括類別、建構子、公開、私有、受保護等等的概念。同時,也介紹了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射等進階特性。
Thumbnail
這個章節主要介紹了Swift程式語言中物件導向程式設計的基本概念,包括類別、建構子、公開、私有、受保護等等的概念。同時,也介紹了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射等進階特性。
Thumbnail
此章節旨在解釋Swift語言中函數的基本結構和操作方式,包括函數的聲明、呼叫、參數和返回值。閱讀這個章節可以幫助你理解並掌握如何在Swift編程中有效地使用和管理函數。
Thumbnail
此章節旨在解釋Swift語言中函數的基本結構和操作方式,包括函數的聲明、呼叫、參數和返回值。閱讀這個章節可以幫助你理解並掌握如何在Swift編程中有效地使用和管理函數。
Thumbnail
本篇介紹了Swift程式語言中的各種流程控制元素,包括條件語句(如if, else if, else),三元運算子,多條件分支判斷的switch語句,以及各種迴圈(如for迴圈,while迴圈,以及repeat-while迴圈)。同時也詳細解釋了如何進行迴圈嵌套,以及如何使用控制迴圈語句。
Thumbnail
本篇介紹了Swift程式語言中的各種流程控制元素,包括條件語句(如if, else if, else),三元運算子,多條件分支判斷的switch語句,以及各種迴圈(如for迴圈,while迴圈,以及repeat-while迴圈)。同時也詳細解釋了如何進行迴圈嵌套,以及如何使用控制迴圈語句。
Thumbnail
本章節介紹了如何建立並設置Swift項目以及如何選擇和設置Swift代碼編輯器。這包括在Xcode和命令行中建立Swift項目,選擇Xcode、Visual Studio Code或AppCode作為編輯器,以及如何使用SPM安裝插件。
Thumbnail
本章節介紹了如何建立並設置Swift項目以及如何選擇和設置Swift代碼編輯器。這包括在Xcode和命令行中建立Swift項目,選擇Xcode、Visual Studio Code或AppCode作為編輯器,以及如何使用SPM安裝插件。
Thumbnail
本章節旨在為讀者提供Swift程式語言的基礎知識,包括其基本語法、註解方法和變數使用方式,並通過具體的程式碼示例來說明這些概念。這將幫助讀者理解Swift的基本結構,並學會如何在Swift中定義變數並使用註解。
Thumbnail
本章節旨在為讀者提供Swift程式語言的基礎知識,包括其基本語法、註解方法和變數使用方式,並通過具體的程式碼示例來說明這些概念。這將幫助讀者理解Swift的基本結構,並學會如何在Swift中定義變數並使用註解。
Thumbnail
這份文件的目的是介紹Swift語言,包括它的特性、應用範疇,以及誰在使用它。它也提供了一些學習Swift的資源和工具,以及一些常見的Swift庫和框架。
Thumbnail
這份文件的目的是介紹Swift語言,包括它的特性、應用範疇,以及誰在使用它。它也提供了一些學習Swift的資源和工具,以及一些常見的Swift庫和框架。
Thumbnail
Part.1 搞定基本的 UI 開始開發 iOS App。 首先準備一台 Mac,然後安裝 Xcode,新增專案,系統即刻生成基本的專案結構。coding 的起點在檔案 ContentView.swift: import SwiftUI struct ContentView: View {  
Thumbnail
Part.1 搞定基本的 UI 開始開發 iOS App。 首先準備一台 Mac,然後安裝 Xcode,新增專案,系統即刻生成基本的專案結構。coding 的起點在檔案 ContentView.swift: import SwiftUI struct ContentView: View {  
Thumbnail
觀察者模式透過主題訂閱/訊息通知的機制,極度增強系統的可擴展性、靈活性以及降低組件間的耦合度。概念直觀簡單,是非常實用的設計模式。
Thumbnail
觀察者模式透過主題訂閱/訊息通知的機制,極度增強系統的可擴展性、靈活性以及降低組件間的耦合度。概念直觀簡單,是非常實用的設計模式。
Thumbnail
在寫SwiftUI view的時候,碰到一個瓶頸(? 帶有Binding的參數要如何preview。 舉例來說有個右邊圖片左邊文字的View,給他一個@Binding var isActive: Bool的狀態,當active時圖片要跟著改變: struct RightImageView: Vie
Thumbnail
在寫SwiftUI view的時候,碰到一個瓶頸(? 帶有Binding的參數要如何preview。 舉例來說有個右邊圖片左邊文字的View,給他一個@Binding var isActive: Bool的狀態,當active時圖片要跟著改變: struct RightImageView: Vie
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News