AAH*_*AAH 4 asynchronous swift google-cloud-firestore swiftui
我知道有几个具有类似结构的问题,但我真的很难让我的代码调用检索 Firestore 数据的方法,等到异步函数完成后再返回。
目前我有调用 的父函数getPledgesInProgress
,该方法从 firebase 检索数据。初始化父级时会调用此方法。
@State var pledgesInProgress = [Pledge]()
var pledgePicked: Pledge?
var body: some View {
VStack{
//LOTS OF CODE HERE WHICH ISN'T RELEVANT
}
func initVars(){
pledgesInProgress = getPledgesInProgress(pledgePicked: pledgePicked ?? emptyPledge)
}
}
Run Code Online (Sandbox Code Playgroud)
问题在于,pledgesInProgress 变量使用空数组进行初始化,因为父级不会等到被调用函数完成获取 Firestore 文档后再继续。
func getPledgesInProgress(pledgePicked: Pledge)-> [Pledge]{
let db = Firestore.firestore()
var pledgesToReturn = [Pledge]() //INITIALISED AS EMPTY
db.collection("Pledges")
.getDocuments { (snapshot, error) in
guard let snapshot = snapshot, error == nil else {
//handle error
return
}
snapshot.documents.forEach({ (documentSnapshot) in
let documentData = documentSnapshot.data()
pledgesToReturn.append(findPledgeWithThisID(ID: documentData["ID"] as! Int))
})
}
//PROBLEM!!!! returned before getDocuments() completed
return pledgedToReturn
}
Run Code Online (Sandbox Code Playgroud)
问题是数组 pledgesToReturn 在 getDocuments() 方法完成之前返回,因此每次都以空数组形式返回。请有人帮助我了解如何让方法等待此调用完成?谢谢
NB Pledge 是自定义数据类型,但这并不重要,重要的是了解如何等待异步函数完成。你可以用任何你喜欢的数据类型替换 Pledge 数据类型,它仍然是相同的原理
Pet*_*ese 13
火霸在这里。首先,请知道大多数(!)Firebase API 都是异步的,并且要求您使用完成处理程序来接收结果。随着 async/await 的普遍可用性,这将变得更容易,这将使您能够编写直线代码。我不久前录制了一个有关此内容的视频 -请观看该视频以了解如何将 Firebase 与 Swift 5.5 结合使用。
\n有两种方法可以解决此问题:使用完成处理程序或使用 async/await。我将在下面描述这两者,但请注意 async/await 仅在 Swift 5.5 中可用并且需要 iOS 15,因此如果您正在开发一个应用程序并希望将其交付给使用该应用程序的用户,您可能需要选择完成处理程序iOS 14.x 及更低版本。
\n这是当前处理 Firebase API 结果的方式。
\n这是代码的更新版本,使用完成处理程序:
\nfunc getPledgesInProgress(pledgePicked: Pledge, completionHandler: ([Pledges]) -> Void) {\n \n let db = Firestore.firestore()\n var pledgesToReturn = [Pledge]() //INITIALISED AS EMPTY\n\n \n db.collection("Pledges")\n .getDocuments { (snapshot, error) in\n guard let snapshot = snapshot, error == nil else {\n //handle error\n return\n }\n \n snapshot.documents.forEach({ (documentSnapshot) in\n let documentData = documentSnapshot.data()\n pledgesToReturn.append(findPledgeWithThisID(ID: documentData["ID"] as! Int))\n })\n\n // call the completion handler and pass the result array\n completionHandler(pledgesToReturn]\n }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n这是视图:
\n\nstruct PledgesInProgress: View {\n @State var pledgesInProgress = [Pledge]()\n var pledgePicked: Pledge?\n\n var body: some View {\n VStack { \n // LOTS OF CODE HERE WHICH ISN\'T RELEVANT\n }\n .onAppear {\n getPledgesInProgress(pledgePicked: pledgePicked) { pledges in\n self.pledgesPicked = pledges\n }\n }\n } \n}\n
Run Code Online (Sandbox Code Playgroud)\n您的原始代码非常接近异步/等待实现的代码。要记住的主要事项是:
\nasync
await
@MainActor
task
视图修饰符在视图出现时执行代码。或者,如果您想从按钮处理程序或另一个同步上下文进行调用,请将调用包装在async { await callYourAsyncFunction() }
.要了解更多相关信息,请查看我的文章《SwiftUI 中的 async/await 入门》(视频即将推出)。我有一篇关于 async/await 和 Firestore 的文章正在酝酿中 - 一旦它上线,我将更新这个答案。
\nfunc getPledgesInProgress(pledgePicked: Pledge) async -> [Pledges] {\n \n let db = Firestore.firestore()\n var pledgesToReturn = [Pledge]() //INITIALISED AS EMPTY\n\n let snapshot = try await db.collection("Pledges").getDocuments()\n snapshot.documents.forEach { documentSnapshot in\n let documentData = documentSnapshot.data()\n pledgesToReturn.append(findPledgeWithThisID(ID: documentData["ID"] as! Int))\n }\n\n // async/await allows you to return the result just like in a normal function:\n return pledgesToReturn\n }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n这是视图:
\nfunc getPledgesInProgress(pledgePicked: Pledge) async -> [Pledges] {\n \n let db = Firestore.firestore()\n var pledgesToReturn = [Pledge]() //INITIALISED AS EMPTY\n\n let snapshot = try await db.collection("Pledges").getDocuments()\n snapshot.documents.forEach { documentSnapshot in\n let documentData = documentSnapshot.data()\n pledgesToReturn.append(findPledgeWithThisID(ID: documentData["ID"] as! Int))\n }\n\n // async/await allows you to return the result just like in a normal function:\n return pledgesToReturn\n }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n有几件事可以使您的代码更具弹性:
\nif let
、guard let
、带或不带默认值的可选展开。查看Swift 中的选项:终极指南 \xe2\x80\x93 LearnAppMaking了解更多详细信息。 归档时间: |
|
查看次数: |
3532 次 |
最近记录: |