SwiftUI UserDefaults 干扰 Firebase Firestore 数据
Posted
技术标签:
【中文标题】SwiftUI UserDefaults 干扰 Firebase Firestore 数据【英文标题】:SwiftUI UserDefaults interfering with Firebase Firestore data 【发布时间】:2021-02-18 19:20:35 【问题描述】:我正在使用 Google Firebase 的 Cloud Firestore 服务和一个 SwiftUI 项目,该项目基于每个地图详细说明视频游戏中的策略。我正在使用视图、视图模型、模型架构。值得注意的是,我使用 Swift 包管理器来导入 API,而不是 CocoaPods。
我有一个 ScrollView,其中包含从 Firestore 集合中获取的一些地图。点击地图将向用户展示另一个 ScrollView,其中列出了从 Firestore 中的单独集合中获取的策略。我遇到的问题是,每当更改 UserDefault(使用 UserDefaults.standard.setValue(...)
或 @AppStorage("settingName") var...
)时,ScrollView 的内容就会消失。 Firestore 数据和 UserDefaults 之间没有任何关系(没有从一个保存到另一个)。
这只发生在细节视图,而不是主视图,尽管代码从一个 ViewModel swift 文件复制并粘贴到另一个。
这是 StratsViewModel.swift 代码:
class StratsViewModel: ObservableObject
@Published var strats = [Strat]()
private var db = Firestore.firestore()
func fetchData(forMap: String)
if strats.isEmpty
db.collection("maps/\(forMap)/strats").getDocuments (querySnapshot, error) in
guard let documents = querySnapshot?.documents else
return
self.strats = documents.map (queryDocumentSnapshot) -> Strat in
let data = queryDocumentSnapshot.data()
let id = queryDocumentSnapshot.documentID
let name = data["name"] as? String ?? ""
let map = data["map"] as? String ?? ""
let type = data["type"] as? String ?? ""
let side = data["side"] as? String ?? ""
let strat = Strat(id: id, name: name, map: map, type: type, side: side)
return strat
在 MapsDetailView.swift(由 MapsView.swift 提供)的 ScrollView 中,策略显示如下:
struct MapsDetailView: View
var map: Map
@ObservedObject private var viewModel = StratsViewModel()
var body: some View
ScrollView
ForEach(viewModel.strats, id: \.self) strat in
NavigationLink(destination: StratView())
StratCell(strat: strat)
.onAppear()
self.viewModel.fetchData(forMap: map.id)
如果我要在视图中添加一个按钮,例如,为 UserDefaults 中的任何键设置任何值,则 ScrollView 中的几十个项目就会消失。
.toolbar
ToolbarItem(placement: .navigationBarTrailing)
Button
UserDefaults.standard.setValue("test", forKey: "testKey")
label:
Text("Don't press me!")
使用 TabBar 导航到另一个视图,然后返回 MapDetailView 将触发 .onAppear
方法,但是,在上面显示的 ForEach
行中添加一个断点,表明此循环不会再次运行,直到视图完全关闭并重新打开。
在 TabBar 中切换选项卡时也会出现此问题,因为在出现时,每个视图都会设置一个 tabSelection 键来记住用户在应用程序被终止时最后选择的选项卡。从一个选项卡切换回 MapsDetailView 选项卡将删除 ScrollView 中的所有单元格。
有什么想法吗?如有必要,乐于分享更多源代码。
【问题讨论】:
也许 viewModel 正在重新初始化但 .fetchData 没有被调用?尝试将@ObservedObject 更改为@StateObject。 【参考方案1】:初始化viewModel
时,应使用@StateObject
而不是@ObservedObject
。这两个属性包装器几乎相同,除了@StateObject
将确保在更新/重新渲染视图时对象保持“活动”,而不是重新初始化。以下是有关此主题的一些重要资源:
What is @StateObject?
@ObservedObject vs @StateObject vs @EnvironmentObject
【讨论】:
以上是关于SwiftUI UserDefaults 干扰 Firebase Firestore 数据的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:如何使用 UserDefaults 保存选择器数据?
如何在 SwiftUI 中将 Stepper 数据保存到 UserDefaults?
SwiftUI 从 UserDefaults.standard 存储和提取字典
在 SwiftUI 中使用 UserDefaults 进行全局更新