我使用Swift,SwiftUI和Cloud Firestore运行了一个移动应用程序项目,我需要根据他们的不同设置/偏好来查找用户。我已经通过使用collectionGroup查询解决了这一问题。但是有时(可能是十分之一)查询会崩溃,而没有任何(对我而言)可理解的错误消息。组合索引是使用XCode提供的http链接创建的。
这是我使用的功能:
func getUsersFromActivityPrefs(genders:[String], activities:[Int],skillScore_min:Int, skillScore_max:Int,completion:@escaping ([String]) -> ()) {
var matchUsers = [String]()
var count = 0
let db = Firestore.firestore()
for gender in genders {
for activity in activities {
let dbRef = db.collectionGroup("activity_preferences")
.whereField("gender", isEqualTo: gender)
.whereField("activityid", isEqualTo: activity)
.whereField("status", isEqualTo: true)
.whereField("skill_score", isGreaterThanOrEqualTo: skillScore_min)
.whereField("skill_score", isLessThanOrEqualTo: skillScore_max)
.limit(to: 100)
dbRef.getDocuments {( snap, err) in
count+=1
if err != nil {
print(err!.localizedDescription)
}
for i in snap!.documentChanges{
let uid = i.document.get("uid") as? String ?? ""
if uid != "" && !matchUsers.contains(uid) {
matchUsers.append(uid)
if matchUsers.count == 100 {
count = genders.count * activities.count
completion(matchUsers) //escaping completion handler
return
}
}
}
if count == genders.count * activities.count {
completion(matchUsers)
return
}
}
}
}
}
我已经附上了XCode的跟踪日志和崩溃消息。我正在使用最新版本的Firebase SDK,部署目标是iOS14。 这是我得到的跟踪日志:
线程#1,队列='com.apple.main-thread',停止原因= EXC_BAD_ACCESS(代码= 1,地址= 0x4f)
帧#0:0x00007fff4b80dd66 AttributeGraph AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 322 frame #1: 0x00007fff4b81f1a5 AttributeGraph
AGGraphGetValue + 203
框架2:0x00007fff55e7ffab SwiftUI SwiftUI.DynamicBody.phase.getter : SwiftUI._GraphInputs.Phase + 27 frame #3: 0x00007fff55e80176 SwiftUI
SwiftUI.DynamicBody.updateValue()->()+ 294
框架#4:0x00007fff55b9583a SwiftUI partial apply forwarder for implicit closure #2 (Swift.UnsafeMutableRawPointer, __C.AGAttribute) -> () in implicit closure #1 (A1.Type) -> (Swift.UnsafeMutableRawPointer, __C.AGAttribute) -> () in closure #1 () -> (Swift.UnsafeMutableRawPointer, __C.AGAttribute) -> () in closure #1 (Swift.UnsafePointer<A1>) -> AttributeGraph.Attribute<A> in AttributeGraph.Attribute.init<A where A == A1.Value, A1: AttributeGraph.StatefulRule>(A1) -> AttributeGraph.Attribute<A> + 26 frame #5: 0x00007fff4b808d03 AttributeGraph
AG :: Graph :: UpdateStack :: update()+ 505
框架6:0x00007fff4b809199 AttributeGraph AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335 frame #7: 0x00007fff4b80d8e8 AttributeGraph
AG :: Graph :: value_ref(AG :: AttributeID,AGSwiftMetadata const *,bool *)+ 130
框架#8:0x00007fff4b81f1f3 AttributeGraph AGGraphGetValue + 281 frame #9: 0x00007fff561aeeb7 SwiftUI
SwiftUI.GraphHost.updatePreferences()-> Swift.Bool + 39
框架#10:0x00007fff55c9a8cf SwiftUI SwiftUI.ViewGraph.updateOutputs(at: SwiftUI.Time) -> () + 95 frame #11: 0x00007fff5611310c SwiftUI
封闭#1()->()in(在SwiftUI中的扩展名):SwiftUI.ViewRendererHost.render(时间间隔:Swift.Double,updateDisplayList:Swift.Bool)->()+ 1308
框架#12:0x00007fff56112327 SwiftUI (extension in SwiftUI):SwiftUI.ViewRendererHost.render(interval: Swift.Double, updateDisplayList: Swift.Bool) -> () + 343 frame #13: 0x00007fff55ba07de SwiftUI
关闭#1()->()在SwiftUI._UIHostingView.requestImmediateUpdate()->()+ 62
框架#14:0x00007fff562739ae SwiftUI reabstraction thunk helper from @escaping @callee_guaranteed () -> () to @escaping @callee_unowned @convention(block) () -> () + 14 frame #15: 0x0000000112ebd8ac libdispatch.dylib
_ dispatch_call_block_and_release + 12
框架16:0x0000000112ebea88 libdispatch.dylib _dispatch_client_callout + 8 frame #17: 0x0000000112eccf23 libdispatch.dylib
_ dispatch_main_queue_callback_4CF + 1152
框架#18:0x00007fff203a8276 CoreFoundation __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 frame #19: 0x00007fff203a2b06 CoreFoundation
__ CFRunLoopRun + 2685
框架#20:0x00007fff203a1b9e CoreFoundation CFRunLoopRunSpecific + 567 frame #21: 0x00007fff2b773db3 GraphicsServices
GSEventRunModal + 139
框架#22:0x00007fff24660af3 UIKitCore -[UIApplication _run] + 912 frame #23: 0x00007fff24665a04 UIKitCore
UIApplicationMain + 101
帧#24:0x000000010db84a5b陪练main at AppDelegate.swift:14:7 frame #25: 0x00007fff20257415 libdyld.dylib
开始+ 1
答案 0 :(得分:0)
func getUsersFromActivityPrefs(genders: [String], activities: [Int], skillScore_min: Int, skillScore_max: Int, completion: @escaping ([String]) -> Void) {
var matchUsers = [String]()
var count = 0
let db = Firestore.firestore()
let dispatch = DispatchGroup() // instantiate dispatch group outside loop
for gender in genders {
for activity in activities {
dispatch.enter() // enter group on each iteration
let dbRef = db.collectionGroup("activity_preferences")
.whereField("gender", isEqualTo: gender)
.whereField("activityid", isEqualTo: activity)
.whereField("status", isEqualTo: true)
.whereField("skill_score", isGreaterThanOrEqualTo: skillScore_min)
.whereField("skill_score", isLessThanOrEqualTo: skillScore_max)
.limit(to: 100)
dbRef.getDocuments {( snap, err) in
if let snap = snap {
count += 1
for doc in snap.documents {
if let uid = doc.get("uid") as? String,
!matchUsers.contains(uid) {
matchUsers.append(uid)
}
}
} else if let err = err {
print(err)
}
dispatch.leave() // always leave no matter what the db returned
}
}
}
/*
this is the group's completion handler and it's only
called once after all groups have entered and left
*/
dispatch.notify(queue: .main) {
completion(matchUsers)
}
}