无法在 SwiftUI 按钮视图中从 Cloud Firestore 获取数据
Posted
技术标签:
【中文标题】无法在 SwiftUI 按钮视图中从 Cloud Firestore 获取数据【英文标题】:Cannot fetch data from Cloud Firestore in SwiftUI Button view 【发布时间】:2020-03-30 07:52:59 【问题描述】:为什么这不起作用? Firestore 中有数据,但似乎该块未执行:
import SwiftUI
import FirebaseFirestore
struct ContentView: View
var body: some View
VStack
Button(
action:
print("Getting data...")
let db = Firestore.firestore().collection("menu")
let query = db.order(by: "name", descending: true)
query.getDocuments() snapshot, err in
guard let snapshot = snapshot else
return
print(snapshot)
for doc in snapshot.documents
print(doc)
,
label: Text("Click Me")
)
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【问题讨论】:
一切都是在堆栈上创建的,所以在退出操作时释放,所以被取消。 我试过你的查询,效果很好。您确定您使用的是正确的密钥吗?比如menu
和name
?
是的,确定一个集合称为菜单,一个字段称为名称。
@asperi 你能进一步解释一下吗?该示例来自适用于 Youtube 的教程 - 无法弄清楚我哪里不对。
我很确定 Asperi 没有尝试您的查询。你的menu
收藏下有name
键吗?再次仔细检查,并仔细检查您的项目中是否有正确的 .plist 文件。
【参考方案1】:
您不应将数据访问逻辑添加到按钮的操作处理程序。相反,将数据访问逻辑提取到视图模型(甚至是存储库)中,然后在视图模型的属性上添加订阅,如下所示:
假设的菜单项数据模型:
struct MenuItem: Identifiable
var id: String = UUID().uuidString
var title: String
查看模型:
import Foundation
import FirebaseFirestore
class MenuItemsViewModel: ObservableObject
@Published var menuItems = [MenuItem]()
private var db = Firestore.firestore()
func fetchData()
db.collection("menuitems").addSnapshotListener (querySnapshot, error) in
guard let documents = querySnapshot?.documents else
print("No documents")
return
self.menuItems = documents.map queryDocumentSnapshot -> MenuItem in
let data = queryDocumentSnapshot.data()
let title = data["title"] as? String ?? ""
return MenuItem(id: .init(), title: title)
在你看来:
struct MenuItemsListView: View
@ObservedObject var viewModel = MenuItemsViewModel()
var body: some View
NavigationView
List(viewModel.menuItems) menuItem in
VStack(alignment: .leading)
Text(menuItem.title)
.font(.headline)
.navigationBarTitle("Menu")
.onAppear() // (3)
self.viewModel.fetchData()
使用 Firestore 的 Codable 支持可以进一步简化数据映射:
以下是您需要更新模型的方法:
import FirebaseFirestoreSwift
struct MenuItem: Identifiable, Codable
@DocumentID var id: String? = UUID().uuidString
var title: String
这里是更新的fetchData()
方法:
func fetchData()
db.collection("menuitems").addSnapshotListener (querySnapshot, error) in
guard let documents = querySnapshot?.documents else
print("No documents")
return
self.menuItems = documents.compactMap (queryDocumentSnapshot) -> MenuItem? in
return try? queryDocumentSnapshot.data(as: MenuItem.self)
如果这不起作用,请检查日志是否有任何错误消息(例如,您的安全规则可能会阻止您读取数据)。
【讨论】:
以上是关于无法在 SwiftUI 按钮视图中从 Cloud Firestore 获取数据的主要内容,如果未能解决你的问题,请参考以下文章
在 SwiftUI 中从 UIViewController 调用函数