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

推荐订阅源

MyScale Blog
MyScale Blog
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
N
News and Events Feed by Topic
Recent Announcements
Recent Announcements
D
Docker
M
MIT News - Artificial intelligence
L
LangChain Blog
I
InfoQ
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Proofpoint News Feed
博客园_首页
MongoDB | Blog
MongoDB | Blog
美团技术团队
S
Schneier on Security
G
GRAHAM CLULEY
月光博客
月光博客
有赞技术团队
有赞技术团队
Vercel News
Vercel News
Scott Helme
Scott Helme
P
Privacy International News Feed
Last Week in AI
Last Week in AI
Recorded Future
Recorded Future
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The Cloudflare Blog
Attack and Defense Labs
Attack and Defense Labs
Google Online Security Blog
Google Online Security Blog
Simon Willison's Weblog
Simon Willison's Weblog
量子位
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
V
Visual Studio Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
NISL@THU
NISL@THU
N
Netflix TechBlog - Medium
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Spread Privacy
Spread Privacy
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
小众软件
小众软件
罗磊的独立博客
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Threatpost
L
Lohrmann on Cybersecurity
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Security Affairs
Cloudbric
Cloudbric
爱范儿
爱范儿
H
Heimdal Security Blog
PCI Perspectives
PCI Perspectives

肘子的 Swift 记事本 | Fatbobman's Blog

当每一次写入都有了新价格 -- 肘子的 Swift 周报 #144 当 Linux 成为“空气”:容器、Agent 与不再重要的“桌面之争” -- 肘子的 Swift 周报 #143 两个 SwiftUI 动画 Bug 排查小记 SPI 加入 Apple,Swift 迈向自举 -- 肘子的 Swift 周报 #142 Swift 还让你 Excited 吗? -- 肘子的 Swift 周报 #141 从 Size Class 到可用空间,horizontalSizeClass 还可靠吗? WWDC 26:AI 帮你看完了,然后呢? -- 肘子的 Swift 周报 #140 WWDC 2026 初印象:符合预期,但更务实 -- 肘子的 Swift 周报 #139 Core Data + Observation:从属性级响应到心智解放 稳定 > 新功能 -- 肘子的 Swift 周报 #138 用自定义 Layout 化解 SwiftUI List 的行高与间距跳变 从社区路标到生态基石:Dave Verwer 的新篇章 -- 肘子的 Swift 周报 #137 消失的 WWDC 愿望单 -- 肘子的 Swift 周报 #136 CocoaPods 正在退场,SwiftPM 才刚到第二章 -- 肘子的 Swift 周报 #135 让 AI 从称手到称心 -- 肘子的 Swift 周报 #134 Swift 并发正被更广泛地接纳 -- 肘子的 Swift 周报 #133 从 OpenSwiftUI 到 DanceUI:换个方式 Dive SwiftUI -- 肘子的 Swift 周报 #132 被 Vibe 摧毁的版权壁垒,与开发者的新护城河 -- 肘子的 Swift 周报 #131 苹果的罕见妥协:当高危漏洞遇上“拒升”潮 -- 肘子的 Swift 周报 #130 一墙之隔,不同的时空 -- 肘子的 Swift 周报 #129 我的 App 审核被卡了? -- 肘子的 Swift 周报 #128 CDE:一次让 Core Data 更像现代 Swift 的尝试 50 岁的苹果和 51 岁的我 -- 肘子的 Swift 周报 #127 2026 年,为什么我仍在思考 Core Data Macbook Neo:苹果重回校园的起点 -- 肘子的 Swift 周报 #126 跨域传递 NSManagedObjectContext 为什么在 Swift 6.2 中不再报错?真正的变化不在编译器 Xcode 26.3 + Claude Agent:模型替换、MCP、Skill 与自适应配置 macOS 录屏软件开发实录:从像素抓取到元数据重现 isolated(any) 与 #isolation:让 Swift 闭包自动继承隔离域 在 tvOS 上活下來:一個非典型播放器的工程實錄 告别“可移植汇编”:我已让 Swift 在 MCU 上运行七年 独立开发者的试炼:Zipic 从 0 到 1 的产品化之路 逃离 Mac App Store:如何从零构建独立应用的分发与售卖体系 Partytown 实战:修复 GTM 自定义事件与 dataLayer 失效问题 Swift 6 编译加速:启用 Swift-Syntax 预构建 (Prebuilts) Swift 模块化:使用 package 关键字实现 Target 间安全共享 Monorepo 实战:解决 VSCode/Cursor 中 SwiftLint 配置失效问题 VSCode/Cursor 测试 Core Data:手动编译 xcdatamodeld 指南
为什么父视图无法修改子视图的 @State
东坡肘子 · 2025-12-18 · via 肘子的 Swift 记事本 | Fatbobman's Blog

核心摘要@State 旨在管理视图的内部私有状态,其初始值仅在视图 第一次建立标识(Identity) 时生效;若需持续响应外部数据的变化,请使用 @Binding 或普通的 let 属性。

问题现象

很多 SwiftUI 初学者经常会遇到这样一个“奇怪”的现象:

一个子视图包含两个参数,一个使用 @State 修饰,另一个没有。在父视图中更新这两个参数对应的数据源时,只有没有标注 @State 的属性会随之更新,而标注了 @State 的属性则“无动于衷”。

struct SubView: View {
    let normalValue: String
    @State var stateValue: String // 父视图更新时,这里不会变
    
    // ...
}

@State 的核心语义

SwiftUI 作为一个声明式响应框架,@State 是其最基础的状态管理工具。它的核心语义只有一条:

由 SwiftUI 运行时负责存储和管理内存,确保由 @State 持有的值,其生命周期与视图的生命周期(Identity)完全一致。

这意味着 @State 显式地定义了一个“私域”属性。一旦视图被分配了存储空间,该属性就由视图内部全权接管。

@State var name = "abc"
// 语义上等同于
@State private var name = "abc"

因此,苹果官方文档和最佳实践都强烈建议将 @State 声明为 private,以强化这一概念:这是视图的私有财产,不应由外部干涉。

为什么父视图无法修改它?

为了贯彻 @State 的语义,SwiftUI 在底层实现中采用了类似“一次性初始化”的策略。

  1. 首次创建:当视图第一次被加载到视图树中(建立 Identity)时,SwiftUI 会根据构造函数(init)中传入的参数,初始化 @State 的内部存储(State<T>)。
  2. 后续更新:当父视图刷新并重新调用子视图的 init 方法时,虽然传入了新的参数值,但 SwiftUI 检测到该视图的存储已经存在。为了保持状态的连续性(即防止用户输入的内容丢失),SwiftUI 会直接忽略 init 中传入的新值,继续使用内部存储中现有的值。

简单来说,@State 就像一个只在搬新家时才接受礼物的盒子,之后的每一次拜访,它都会拒绝接收新的礼物,以保护盒子里已有的东西。

扩展阅读:如果你对底层实现感兴趣,可以深入了解 DynamicProperty 协议@State 在内部维护了一个状态枚举,只有在特定的初始化阶段才会接受外部赋值。

解决方案与实践总结

  1. 区分数据源

    • 如果数据由父视图拥有并控制,子视图只负责展示,请使用普通的 let 属性。
    • 如果子视图需要修改这份数据并同步回父视图,请使用 @Binding
    • 只有当数据是子视图完全私有的内部状态(如按钮的高亮状态、输入框的临时内容)时,才使用 @State
  2. 强制刷新(不推荐)

    • 如果确实需要重置 @State,可以通过改变视图的 id.id(value))来强制 SwiftUI 销毁并重建视图,从而触发新的初始化流程。但这会带来性能开销和状态丢失。
  3. 引用类型的新选择

    • 从 iOS 17 起,配合 Observation 框架,@State 取代 @StateObject 用于持有 Observable 对象。
    • ⚠️ 注意性能:与 @StateObject 不同,@State 不具备懒加载(Lazy Initialization)机制。请避免在 View 的 init 或属性默认值中直接初始化开销巨大的引用类型对象,否则每次视图重绘都会导致对象被重复创建(尽管之后会被立即丢弃)。在确实需要使用懒加载的场景,可以通过自定义 @LazyState 来应对
// ❌ 避免这样做,HeavyObject 会被重复创建
@State private var store = HeavyObject() 
   
// ✅ 推荐:在 onAppear 中或使用 lazy 模式初始化

相关提示

订阅 Fatbobman 周报

每周精选 Swift 与 SwiftUI 开发技巧,加入众多开发者的行列。

立即订阅