惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
WordPress大学
WordPress大学
Vercel News
Vercel News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
小众软件
小众软件
L
LangChain Blog
雷峰网
雷峰网
D
DataBreaches.Net
博客园 - 三生石上(FineUI控件)
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tor Project blog
NISL@THU
NISL@THU
Scott Helme
Scott Helme
量子位
S
Security Affairs
T
Threat Research - Cisco Blogs
博客园_首页
云风的 BLOG
云风的 BLOG
D
Docker
AWS News Blog
AWS News Blog
腾讯CDC
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
U
Unit 42
Recent Announcements
Recent Announcements
Apple Machine Learning Research
Apple Machine Learning Research
G
Google Developers Blog
T
The Exploit Database - CXSecurity.com
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LINUX DO - 热门话题
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The Last Watchdog
The Last Watchdog
C
Cybersecurity and Infrastructure Security Agency CISA
IT之家
IT之家
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
F
Full Disclosure
L
Lohrmann on Cybersecurity
The Hacker News
The Hacker News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Y
Y Combinator Blog
S
Security @ Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Check Point Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
N
News and Events Feed by Topic
PCI Perspectives
PCI Perspectives
I
InfoQ

看川博客

我被 AI "蒸馏" 了 - 看川博客 距离上线只差一个软件著作权证书 - 看川博客 开发简报(2):开发者需要先进的工具 - 看川博客 比越狱更棘手!iOS vPhone 虚拟机成黑灰产新温床 - 看川博客 开发简报(1):拥抱 AI、别无选择 - 看川博客 糟糕!我的 OpenClaw 中了病毒 - 看川博客 今天你用了多少词元? - 看川博客 闪忆 LiveMem:把回忆做成会动的壁纸 - 看川博客 视频帧截图(Video2Frame)专业视频抽帧截图工具 - 看川博客 录音记事本 - 专业安全的录音工具 App - 看川博客 Swift 从 ObservableObject 迁移到 @Observable 从 Apple Distribution Managed 证书提取备案所需公钥和 SHA1 条码助手 iOS 2.0.0 升级指南 - 看川博客 SwiftUI Menu checkmark 文本对齐 - 看川博客 C++ RTTI 信息对二进制体积和安全性的影响 - 看川博客 SwiftUI 系统颜色表查询 - 看川博客 读马伯庸《长安的荔枝》 - 看川博客 SwiftUI List selection 的使用提示 - 看川博客 PHP json_encode UTF-8 中文编码问题 - 看川博客 我为什么重新运营微信公众号 - 看川博客 使用 TrollStore(巨魔) 在非越狱设备上安装任意 IPA - 看川博客 条码助手小程序更新 - 看川博客 iOS 18 中 libdyld.dylib/dyld 的一些变化 涨粉神器?解密“抖音黑科技”云端商城 - 看川博客
Swift 从 ObservableObject 迁移到 @Observable 的再讨论
2025-12-01 · via 看川博客

@Observable 不能直接用于 Actor 类型

@Observable 可以作用于 class 和 struct,不能作用于 Actor。Actor 类型的底层实现与 @Observable 的状态观察逻辑存在冲突,比如 Actor 的状态访问需要异步传递,而 @Observable 依赖同步的属性访问来触发观察。Swift 编译器明确禁止将 @Observable 应用在 actor 声明的类型上。比如下方代码:

@Observable
actor ChuanActor {
}

编译期间就会报错:'@Observable' cannot be applied to actor type 'ChuanActor'。

解决办法一般是将 ChuanActor 中需要被观察的数据抽离到使用 @Observable 标记的结构体中。

@Observable + @MainActor

在实际开发中,在需要处理 UI 更新等场景时,@MainActor + @Observable 是非常常见的组合。@MainActor 属性包装器确保了被修饰的类型的属性访问、方法执行必须在主线程,而 @Observable 的状态观察本身也需要在主线程执行。两者的结合强化了线程安全:@Observable 负责状态观察,@MainActor 保证状态的读写和观察通知都在主线程执行,避免了多线程下的 UI 刷新问题。

对 @Observable 属性的 Binding

struct UserForm: View {
    @Environment(UserProfile.self) private var profile
    
    var body: some View {
        Form {
            TextField("Name", text: $profile.name)
            TextField("Age", text: $profile.age)
        }
    }
}

@Environment 获取的对象默认不是可绑定的,上述代码 $profile.name 这里就会报错。除了可以在子视图中将 @Observable 属性声明为 @Bindable:

struct UserForm: View {
    @Environment(UserProfile.self) private var profile
    
    var body: some View {
        UserFormSub(profile: $profile)
    }
}

struct UserFormSub: View {
    @Bindable var profile: UserProfile
    
    var body: some View {
        Form {
            TextField("Name", text: $user.name)
            TextField("Age", text: $user.eag)
        }
    }
}

还可以直接在当前视图内定义 @Bindable 变量:

struct UserForm: View {
    @Environment(UserProfile.self) private var profile
    
    var body: some View {
		// 使用 @Bindable 修饰
		@Bindable var bindableprofile = profile

        Form {
            TextField("Name", text: $bindableprofile.name)
            TextField("Age", text: $bindableprofile.age)
        }
    }
}

@AppStorage 和 @Observable 同时使用的问题

@Observable
final class Preference {
	@AppStorage("chuan_sort_by")  var sort_by: SortBy = .date_created
	@AppStorage("chuan_sort_order") var sort_order: SortOrder = .reverse
}

上面这段代码会报错:Invalid redeclaration of synthesized property。

原因:@Observable 宏会自动为所有存储属性生成观察功能,与 @AppStorage 的属性包装器机制存在冲突。

注意:此时不能使用 @ObservationIgnored 修饰 @AppStorage 属性来规避这个问题,会消除报错但会导致 @AppStorage 属性失去可观察性。

SwiftUI 中的 UserDefaults 与 Observation:如何实现精准响应 一文中,作者给出了两个解决方案:

1、不使用 @AppStorage,而是手动实现 get 和 set 方法以操作 UserDefaults

@Observable
class Settings {
    @ObservationIgnored
    var name: String {
        get {
            access(keyPath: \.name)
            return UserDefaults.standard.string(forKey: "name") ?? _nameDefault
        }
        set {
            withMutation(keyPath: \.name) {
                UserDefaults.standard.set(newValue, forKey: "name")
            }
        }
    }
}

2、使用作者开源的 ObservableDefaults

withObservationTracking

Swift Observation 框架同时还提供了一个 withObservationTracking 函数,开发者可以用它来跟踪 Observable 对象的属性是否发生变化。

public func withObservationTracking<T>(_ apply: () -> T, onChange: @autoclosure () -> @Sendable () -> Void) -> T

withObservationTracking 接受两个闭包参数:apply 和 onChange。使用时将需要监听的属性放在 apply 闭包中,如果这些属性发生改变其 onChange 闭包将会被调用。

import Observation

@Observable final class Counter {
    var count = 0
}

let counter = Counter()
func startObservation() {
    withObservationTracking {
        // 在 apply 闭包中访问需要观察的属性
        print("当前计数: \(counter.count)")
    } onChange: {
        // 属性变化时,onChange 会被调用
        print("检测到计数变化!")
        
        // 由于 onChange 默认只触发一次,我们递归调用以继续观察
        // 有时为了避免 onChange 在实际变化应用前立即运行,可以将其包装在 Task 中
        Task {
            startObservation()
        }
    }
}