为啥这个函数每次运行时都会将对象两次附加到数组中?
Posted
技术标签:
【中文标题】为啥这个函数每次运行时都会将对象两次附加到数组中?【英文标题】:Why does this function append the object twice to the array each time it runs?为什么这个函数每次运行时都会将对象两次附加到数组中? 【发布时间】:2021-03-18 02:57:32 【问题描述】:我正在使用 swift 的 DispatchGroup() 来帮助编排一个 for 循环
在 firesbase 中找到文档 将文档转换为自定义对象 将自定义对象附加到数组中每次传递时,函数最终都会将每个对象两次附加到数组中,我不明白为什么。 这是函数...
func getFriends()
// Initialize the DispatchGroup
let group = DispatchGroup()
// the myFriends array contains documentIDs that I am using to fetch documents from firebase
//
for pid in myFriendObj.myFriends
group.enter()
_ = Firestore.firestore().collection("Players")
.whereField(FieldPath.documentID(), isEqualTo: pid)
.addSnapshotListener [self] querySnapshot, error in
if let error = error
print("Error getting > Players: \(error.localizedDescription)")
return
guard let querySnapshot = querySnapshot else return
self.players.append(
contentsOf: querySnapshot.documents.compactMap document in
try? document.data(as: UserProfile.self)
)
group.leave()
group.notify(queue: DispatchQueue.global(qos: .background))
// I'm currently eliminating the dups via this fancy extends method.
self.players = self.players.removeDuplicates()
:: 更新 ::
在这方面仍然没有运气 - 我什至删除了 dispatchgroup 和 snapshotlistener 回调,并且当类的实例被实例化时,这段代码仍然调用 get() 两次。这是新的、更简单的代码...
class FriendRepository: ObservableObject
private let store = Firestore.firestore()
private let friendPath: String = "MyFriends"
@Published var friendIDs: [String] = []
var userId = ""
private let authenticationService = AuthenticationService()
private var cancellables: Set<AnyCancellable> = []
init()
authenticationService.$user
.compactMap user in
user?.uid
.assign(to: \.userId, on: self)
.store(in: &cancellables)
authenticationService.$user
.receive(on: DispatchQueue.main)
.sink [weak self] _ in
self?.get()
.store(in: &cancellables)
func get( )
store.collection(friendPath).document(userId).getDocument (document, error) in
let result = Result
try document?.data(as: Friends.self)
switch result
case .success(let f):
if let f = f
print("friends:>> \(f.myFriends)")
self.friendIDs = f.myFriends
else
print("Document does not exist")
case .failure(let error):
print("Error decoding city: \(error)")
当一个新实例运行 init() 时,我在控制台中看到了这个...它打印了 friends:>> 语句两次
friends:>> ["PHyUe6mAc3LodM5guJJU"]
friends:>> ["PHyUe6mAc3LodM5guJJU"]
【问题讨论】:
【参考方案1】:每次数据库中发生更改时,您的 addSnapshotListener
闭包都会被调用,其中包含与查询匹配的所有数据 - 即使该数据自上次调用以来没有更改。这通常意味着您需要在回调顶部清空 self.players
,或者循环遍历 documentChanges
集合以确定更改的确切内容。
【讨论】:
谢谢你,弗兰克!所以我一直在修补清除 self.players 但不确定在哪里执行 removeAll() 语句。您提到“在回调的顶部”,但我不确定我正在使用回调。你能指出在哪里放置这条线吗? 闭包/回调是您传递给函数调用的代码块,然后在某个时刻被该函数调用。这里:.addSnapshotListener [self] querySnapshot, error in
里面的代码块是一个回调/闭包,你可以清除if let error = error
上面的列表。
弗兰克,运气不好。我已经大大简化了事情并删除了回调以及调度组,我什至只读取了一个 Firestore 文档,并且在类实例启动时它仍然进行了两次读取。查看新代码:: UPDATED ::
嗯...在那种情况下,我不确定可能是什么问题。我希望有更好的 Swift/SwiftUI 技能的人能看到发生了什么。【参考方案2】:
func getFriends()
// this will empty the players array when ever the get friends function gets called.
self.players.removeAll()
// Initialize the DispatchGroup
let group = DispatchGroup()
// the myFriends array contains documentIDs that I am using to fetch documents from firebase
//
for pid in myFriendObj.myFriends
group.enter()
_ = Firestore.firestore().collection("Players")
.whereField(FieldPath.documentID(), isEqualTo: pid)
.addSnapshotListener [self] querySnapshot, error in
if let error = error
print("Error getting > Players: \(error.localizedDescription)")
return
guard let querySnapshot = querySnapshot else return
self.players.append(
contentsOf: querySnapshot.documents.compactMap document in
try? document.data(as: UserProfile.self)
)
group.leave()
【讨论】:
players.removeAll() 请添加一些代码示例或文档链接以获得更好的答案:)以上是关于为啥这个函数每次运行时都会将对象两次附加到数组中?的主要内容,如果未能解决你的问题,请参考以下文章