swift - 立即更新信息,但前提是在数据库 swift/firebase 中进行了更改
问题描述
在我的应用程序中,我有一个显示新闻的地方,位于 4 个选项卡视图之一中。为了更改信息,与其相关的所有方面都存储在 Firestore 中(标题、副标题、文本)。目前,我正在使用addSnapshotListener
来获取数据,因为每当我更改 firestore 中的数据时,它都会自动立即更新。但是,每次用户单击与新闻视图相关的选项卡视图图标时,都会执行不同的读取数据调用。我知道当用户群增长时会导致大量读数,从而导致每月向 Firebase 支付更高的费用,并且可能会延迟,对吗?为了解决这个问题,我想到的唯一解决方案是addSnapshotListener
改为getDocuments
. 但是,如果我对 Firestore 进行任何更改,用户需要关闭应用程序然后打开它以查看更新的信息。有没有办法立即更新信息,但前提是在数据库中进行了更改?
这就是我从 Firestore 获取信息的方式:
struct Info: Identifiable{
var id: String = UUID().uuidString
var title: String
var subtitle: String
}
class InfoViewModel: NSObject, ObservableObject {
@Published var infos = [Info]()
func fetchData(){
Firestore.firestore().collection("infos").addSnapshotListener { (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {return}
self.infos = documents.compactMap { (queryDocumentSnapshot) -> Info? in
let data = queryDocumentSnapshot.data()
if let title = data["title"] as? String,
let subtitle = data["subtitle"] as? String{
print("info successful")
return Info(title: title, subtitle: subtitle)
}
else{
print("info failed")
return nil
}
}
}
}
}
在我想显示信息的视图中,我有@ObservedObject var infoModel = InfoViewModel()
一个ForEach
来显示数据,然后.onAppear(){self.infoModel.fetchData()}
每次单击 tabView 图标时更改到此视图时,我都会在调试时获得 3x "信息成功,因为我在 infos 集合中存储了 3 个文档。
标签栏视图:
struct TabBar: View{
@State var current = 0
@StateObject var LocationModel = LocationViewModel()
var body: some View{
NavigationView{
TabView(selection: $current) {
HomeView()
.tag(0)
.tabItem {
Image(systemName: "house")
Text("início")
}
SearchView(LocationModel: LocationModel)
.tag(1)
.tabItem {
Image(systemName: "magnifyingglass")
Text("buscar")
}
CalendarView()
.tag(2)
.tabItem {
Image(systemName: "calendar")
Text("histórico")
}
AccountView()
.tag(3)
.tabItem {
Image(systemName: (self.current == 3 ? "person.fill" : "person"))
Text("perfil")
}
}.accentColor(Color("Color"))
}
}
}
显示风暴数据的位置:
struct HomeView: View{
@StateObject var LocationModel = LocationViewModel()
@StateObject var model = ModelData()
@ObservedObject var infoModel = InfoViewModel()
var body: some View{
VStack( spacing: 12) {
ScrollView(.vertical, showsIndicators: false){
ScrollView(.horizontal, showsIndicators: false){
HStack(spacing: 15){
ForEach(infoModel.infos){ info in
HStack(spacing: 20){
Text(info.title)
.frame(height: 220)
.frame(width: 330)
.background(Color.yellow)
.cornerRadius(18)
}
}
}.padding(.horizontal, 15)
.padding(.bottom, 25)
}
}
.navigationBarTitle("").navigationBarHidden(true)
}.navigationBarTitle("").navigationBarHidden(true)
.onAppear(perform: {
LocationModel.locationManager.delegate = LocationModel
self.infoModel.fetchData()
})
.alert(isPresented: $LocationModel.alert, content: {
Alert(title: Text("Mensagem"), message: Text(LocationModel.alertMsg), dismissButton: .destructive(Text("Pronto").foregroundColor(Color.blue)))
})
}
}
解决方案
您的 VC 可以引用管理与 Firestore 的所有通信的控制器。在该控制器中,您可以初始化快照侦听器。这将一次性获取您的所有文档,您可以将其作为状态存储在该控制器中。从那时起,任何 .add、.modified 和 .removed文档更改都可以更改您的控制器所持有的状态,并使用例如闭包来更新 VC。
推荐阅读
- html - 网页中的动态部分
- python - 如何使用两个不同的分隔符将 DataFrame 列拆分为四个部分
- android - Android Studio - 房间查询结果与预期不同
- git - 将文件添加到 github 存储库并从命令行将文件附加到问题
- python - 我正在使用 cnn 进行深度学习(U-net with Vgg16)
- python - 不返回跨度标记 bs4 中的文本
- php - SSL 证书问题:无法获取本地颁发者证书 - Windows Server PHP Global Sign
- python-3.x - 使用重新样式时如何在绘图中获得固定的轴范围
- .net-core - Sonarqube .Net Core 全局工具和 sonar-project.properties
- node.js - Node 如何在多个运行之间共享 process.env?