You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iPad端NavigationSplitView后台返回丢失列表选中状态问题

iPad上NavigationSplitView列表选中状态后台返回丢失的解决办法

问题描述

在iPad设备上,使用NavigationSplitView实现的列表,按下Home键回到桌面再返回应用后,之前选中的列表项状态会丢失;相同场景下使用NavigationView则能正常保留选中状态,且该问题仅出现在iPad,iPhone无此现象。

有问题的NavigationSplitView代码

import SwiftUI
 
struct NavigationSplitViewExample: View {
     private var alphabets = ["A","B","C"]
        @State private var alphabetChosen: String?
 
        var body: some View {
            NavigationSplitView(columnVisibility: .constant(NavigationSplitViewVisibility.all)) {
                List(alphabets, id:\.self,   selection: $alphabetChosen) { alphabets in
                    Text(alphabets)
                }
            } detail: {
                Text(alphabetChosen ?? "0")
                     
            }
        }
}

正常保留状态的NavigationView代码

struct ContentView: View {
     private var alphabets = ["A","B","C"]
      @State private var alphabetChosen: String?

   let columns = Array(repeating: GridItem(.adaptive(minimum: 94, maximum: 120)), count: 3)
   
   var body: some View {
       NavigationView {
           List(alphabets, id:\.self) {   alphabet in
               NavigationLink(destination: Text("chosen \(alphabet)")) {
                                  Text(alphabet)
                              }
               }
           }
       .navigationBarTitle(Text("Alphabets"))
       .navigationViewStyle(StackNavigationViewStyle())
           }
}

问题原因

NavigationSplitView在iPad上的状态管理逻辑和NavigationView存在差异:当应用进入后台时,@State修饰的选中状态变量会被系统重置。NavigationSplitView的列选中状态依赖于自身的绑定变量,而后台恢复时系统没有自动保留这个@State变量的值;反观NavigationView,它通过NavigationLink维护的导航栈自动保留了选中对应的页面状态。

解决方案

方案1:使用@AppStorage持久化状态

@AppStorage会将状态存储到用户默认配置中,跨应用后台恢复、甚至重启都能保留选中状态:

import SwiftUI
 
struct NavigationSplitViewExample: View {
    private var alphabets = ["A","B","C"]
    // 用AppStorage替代State,指定存储键名
    @AppStorage("selectedAlphabet") private var alphabetChosen: String?
 
    var body: some View {
        NavigationSplitView(columnVisibility: .constant(NavigationSplitViewVisibility.all)) {
            List(alphabets, id:\.self, selection: $alphabetChosen) { alphabet in
                Text(alphabet)
            }
        } detail: {
            Text(alphabetChosen ?? "0")
        }
    }
}

方案2:使用@SceneStorage存储场景状态

@SceneStorage是专门为场景状态设计的存储方案,仅保留当前场景的状态,更轻量化,适合仅需后台恢复时保留状态的场景:

import SwiftUI
 
struct NavigationSplitViewExample: View {
    private var alphabets = ["A","B","C"]
    // 用SceneStorage替代State,指定存储键名
    @SceneStorage("selectedAlphabet") private var alphabetChosen: String?
 
    var body: some View {
        NavigationSplitView(columnVisibility: .constant(NavigationSplitViewVisibility.all)) {
            List(alphabets, id:\.self, selection: $alphabetChosen) { alphabet in
                Text(alphabet)
            }
        } detail: {
            Text(alphabetChosen ?? "0")
        }
    }
}

两种方案对比

  • @AppStorage:数据持久化到系统偏好设置,跨场景、跨应用重启有效;
  • @SceneStorage:数据绑定到当前场景,仅在当前场景后台恢复时有效,不会影响其他场景,更适合多窗口场景。

内容的提问来源于stack exchange,提问作者nirav dinmali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:05:25