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

SwiftUI如何在不同视图间保留isFavorite状态,避免切换后重置为默认值

问题根因

  1. 全局hasFavorites函数无法访问MainView中定义的@State countries变量,永远返回空数组,同时你的判断条件写的是count > 1,即使有1个收藏也会判定为无收藏,属于逻辑错误,这是你切换到收藏页看不到内容的直接原因。
  2. 你当前仅修改内存中的countries数组,没有做持久化存储:Bundle中的JSON文件是只读的,APP重启/进程销毁后所有修改都会重置为默认值。

修复步骤

1. 修复收藏判断逻辑

删除全局的hasFavorites函数,在FavoritesView内部新增计算属性判断收藏列表,修正判断条件:

struct FavoritesView: View {
    @Binding var countries: [Country]
    
    // 内部计算收藏列表
    private var favoriteCountries: [Country] {
        countries.filter { $0.isFavorite }
    }
    
    var body: some View {
        // 只要收藏数大于0就正常展示
        if !favoriteCountries.isEmpty {
            Text("用户有收藏内容!")
            // 可在此处添加List展示所有收藏的国家
        } else {
            Text("暂无收藏!")
        }
    }
}

你还可以简化爱心图标切换的代码,无需写重复的if else:

Image(systemName: country.isFavorite ? "heart.fill" : "heart")
    .foregroundColor(.red)
    .onTapGesture {
        countries[index].isFavorite.toggle()
        // 后续加持久化存储调用
    }

2. 添加数据持久化逻辑

由于Bundle中的资源文件不可修改,我们可以把修改后的国家列表存在UserDefaults(或者沙盒Documents目录),启动时优先读取本地存储的版本,不存在再读Bundle默认JSON。
首先新增存取工具方法(你的Country模型已经遵守Codable协议可直接用):

// 存储国家列表到本地
func saveCountries(_ countries: [Country]) {
    guard let encoded = try? JSONEncoder().encode(countries) else { return }
    UserDefaults.standard.set(encoded, forKey: "SavedCountries")
}

// 读取国家列表,优先读本地存储,无则读默认JSON
func loadCountries() -> [Country] {
    guard let savedData = UserDefaults.standard.data(forKey: "SavedCountries"),
          let decoded = try? JSONDecoder().decode([Country].self, from: savedData) else {
        return Bundle.main.decode("Countries.json")
    }
    return decoded
}

修改MainView的初始化逻辑,修改收藏状态后调用存储方法:

struct MainView: View {
    // 启动时优先读本地存储的数据
    @State var countries: [Country] = loadCountries()
      
    var body: some View {
        TabView {
            ContentView(countries: $countries)
                .tabItem {
                    Label("菜单", systemImage: "list.dash")
                }
            MapView()
                .tabItem {
                    Label("地图", systemImage: "map")
                }
            FavoritesView(countries: $countries)
                .tabItem {
                    Label("收藏", systemImage: "heart")
                }
        }
    }
}

最后在爱心点击的toggle之后调用存储方法即可:

.onTapGesture {
    countries[index].isFavorite.toggle()
    saveCountries(countries) // 每次修改后持久化
}

修改完成后,切换Tab、杀APP重启都不会丢失收藏状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:45:05