别让用户切回页面又重来:用 AI + @SceneStorage 保存 iOS 当前状态

别让用户切回页面又重来:用 AI + @SceneStorage 保存 iOS 当前状态

这一技教你用 AI 把属于当前 scene 的标签、筛选和选中项交给 SwiftUI @SceneStorage 恢复,并用 Xcode 模拟器独立验收多窗口互不覆盖以及与 @AppStorage 的边界。

先把「回来后还要不要接着做」写清楚

用户从 App 切出去回个消息,再切回来,发现刚才的标签页、筛选条件或展开位置全没了,通常会把它当成「页面不稳定」。这类信息不属于账号资料,也不是用户主动设置的长期偏好,它们更像是当前这一次使用过程中的临时进度。
SwiftUI 的 @SceneStorage 专门处理这类按场景保存的界面状态。Apple 将它定义为读取和写入持久化、按 scene 隔离的存储,用于自动恢复状态。1 在支持多个窗口的 iPad 场景里,每个窗口也可以保留自己的状态,不会因为另一个窗口切换了标签页就跟着改变。2

这招适合保存什么

先按「状态属于谁」做判断,不要看到任何变量都让 AI 塞进 @SceneStorage
状态更合适的归属例子
当前这个窗口或这次页面使用过程@SceneStorage当前标签页、当前筛选、选中的详情项、某个面板是否展开
用户希望全 App 都记住的偏好@AppStorage深色模式、列表排序、首次启动提示
账号、支付或其它敏感信息不放进 @SceneStorage登录凭证、支付信息、隐私内容
@AppStorage 反映的是 UserDefaults 中的值;@SceneStorage 关注的是按 scene 保存的状态恢复。3 这张表的作用,是先把数据范围定下来,再让 AI 写代码,避免「页面记住了」却把两个窗口的状态错误地绑在一起。

第一步:写一张状态归属表

在打开 AI 编码工具前,先用四列描述一个页面:
  1. 状态名称:例如当前标签页、当前筛选、选中的订单。
  2. 谁应该拥有它:单个 scene、整个 App,还是服务器账号。
  3. 恢复时机:用户切回 App、重新打开窗口,还是每次都回到默认值。
  4. 不能保存的内容:敏感信息、完整业务对象或过大的数据。
例如一个「订单」页面可以这样写:
状态名称谁拥有恢复目标备注
当前标签页当前 scene切回这个页面时回到上次标签用整数或枚举对应值即可
当前筛选当前 scene回到这个窗口时保留筛选只保存筛选条件,不保存整份订单列表
排序方式整个 App用户下次打开任何订单页仍保持选择这是长期偏好,交给 @AppStorage
登录凭证账号或安全存储按账号和安全策略恢复不交给 @SceneStorage
状态表里如果出现「整个订单列表」「完整用户资料」这类大对象,先删掉它们。@SceneStorage 应该只保存恢复界面所需的少量状态;它也不是安全存储,不能放敏感数据。2

第二步:把缺陷单交给 AI

把页面名称和你的状态表填进去,直接给 AI:
请检查「订单页面」为什么在用户切出 App 再回来后,总是回到默认标签和默认筛选。
请只恢复界面状态,不改订单请求、数据模型、接口和业务规则。按照下面的归属处理:当前标签页和当前筛选属于当前 scene,排序方式属于整个 App,登录凭证不参与本次修改。
请在 SwiftUI View 中使用 @SceneStorage 保存当前标签页和当前筛选,只保存可恢复界面的最小值,例如整数、字符串或布尔值。为每个状态使用清楚且不会与其它页面混淆的 key,并保留现有默认值。
请检查两个 scene 同时存在时是否各自保存自己的标签页和筛选。请补充 Preview 或可重复的模拟器验收入口,并说明你改了哪些文件、每个状态为什么放在 @SceneStorage@AppStorage
最小代码结构可以长这样:
struct OrdersView: View {
    @SceneStorage("orders.selectedTab") private var selectedTab = 0
    @SceneStorage("orders.filter") private var filter = "all"

var body: some View {
        // 现有页面内容继续使用 selectedTab 和 filter
        OrdersContent(selectedTab: $selectedTab, filter: $filter)
    }
}
这里的 key 不是随手写的备注,而是保存状态的名字。让 AI 先按页面或功能加上前缀,后面新增相似页面时更容易排查;如果项目已经有统一命名规则,应以项目规则为准。

第三步:先看 AI 有没有保存错东西

编译前,用这组问题审查改动:
  • @SceneStorage 是否放在真正拥有该页面状态的 View 里,而不是塞进网络层或全局单例?
  • 保存的是标签、筛选条件或选中 ID,还是把整份列表和用户资料一起保存了?
  • 两个 scene 使用相同页面时,是否仍能各自显示自己的状态?
  • 排序、主题这类全 App 偏好有没有被误改成 scene 级状态?
  • 登录凭证、支付信息和其它敏感值有没有出现在新增代码里?
  • key 是否足够清楚,默认值是否和原页面一致?
如果 AI 为了「记住页面」改了接口请求或数据加载逻辑,先让它撤回这部分,只保留界面状态恢复。这个技巧的价值是让用户回到原来的工作位置,不是把缓存系统重新做一遍。

第四步:用 Xcode 验收「真的恢复了」

只看代码或重新点击一次页面不够,按下面的顺序复现:
  1. 在 Xcode 模拟器运行 App,进入订单页面。
  2. 切换到一个非默认标签,设置一个容易辨认的筛选条件。
  3. 按模拟器 Home,让 App 进入后台。
  4. 在 Xcode 里点击 Stop,结束这次运行。
  5. 再次运行 App,回到订单页面,检查标签和筛选是否恢复。
  6. 如果 App 支持多个窗口,在两个 scene 中分别设置不同标签和筛选,确认它们没有互相覆盖。
Nil Coalescing 给出的测试顺序也是先改变状态、让 App 进入后台、在 Xcode 停止,再重新运行检查恢复结果;直接从 App 切换器强制退出,可能会清掉 SceneStorage,不适合拿来判断普通状态恢复是否成功。4
验收时再补两条:把筛选恢复后点一次清除,确认页面仍能回到默认状态;关闭一个 scene 后重新打开,确认产品没有把「暂时恢复」误承诺成「永久保存」。

这招的边界

@SceneStorage 适合「用户回来时继续当前操作」,不适合下面三种承诺:
  • 永久偏好:用户明确设置的主题、排序和通知选项,应按 App 范围设计,不要因为当前页面方便就绑定到某个 scene。
  • 业务数据缓存:订单列表、文章正文和用户资料应由现有数据层负责,scene storage 只保留恢复它们所需的 ID 或筛选条件。
  • 安全数据:不要把密码、令牌、支付信息或其它敏感值放进去。它不是安全容器。2
Apple 把状态恢复放在「提供 App 连续使用体验」的语境里,重点是让用户接着当前活动继续操作。5 所以产品验收应该问「用户回来后能不能接着做」,而不是只问「这个值有没有写进存储」。

PM 今天可以独立完成的清单

  • 找一个用户切回页面后经常丢失的标签、筛选、选中项或展开状态。
  • 写清它属于当前 scene、整个 App,还是账号数据。
  • 把缺陷单交给 AI,要求只恢复最小界面状态,不改接口和业务逻辑。
  • 检查新增的 @SceneStorage key、默认值和保存内容。
  • 用「改状态、进后台、Xcode Stop、重新运行」的顺序验收一次。
  • 如果支持多窗口,在两个 scene 设不同状态,确认它们互不覆盖。
先拿一个「当前筛选」或「当前标签」做小改动就够了。它能直接让你看见 @SceneStorage@AppStorage 的边界,也能在不重写业务逻辑的情况下验证 AI 是否真的把用户的工作位置留下来。

Contenido relacionado

  • Inicia sesión para comentar.
More from this channel