【问题标题】:Swift+Firestore - return from getDocument() functionSwift+Firestore - 从 getDocument() 函数返回
【发布时间】:2021-05-25 16:26:31
【问题描述】:

我目前正在处理这个问题。我有 Firestore 数据库。我的目标是在获取后用User 实体填充friends 数组。我调用fetchFriends,它获取当前登录的用户,其中包含friends 数组(每个项目都是朋友的ID)。然后循环friends 数组并获取朋友的每个 ID 并创建新实体 User。我想将此friends 数组映射到friends Published 变量。我在那里所做的不起作用,我无法想出一些解决方案。

Firestore 数据库

User
- name: String
- friends: [String]

用户模型

struct User: Identifiable, Codable {   
    @DocumentID var id: String?
    var name: String?
    var email: String
    var photoURL: URL?
    
    var friends: [String]?
}

用户视图模型

@Published var friends = [User?]()

func fetchFriends(uid: String) {
    
    let userRef = db.collection("users").document(uid)
    
    userRef.addSnapshotListener { documentSnapshot, error in
        
        do {
            guard let user = try documentSnapshot?.data(as: User.self) else {
                return
            }
            
            self.friends = user.friends!.compactMap({ friendUid in
                
                self.fetchUserAndReturn(uid: friendUid) { friend in
                    return friend
                }
            })
        }
        catch {
            print(error)
        }
    }
}

func fetchUserAndReturn(uid: String, callback:@escaping (User)->User) {
    let friendRef = db.collection("users").document(uid)
    
    friendRef.getDocument { document, error in
        callback(try! document?.data(as: User.self) as! User)
    }
}

【问题讨论】:

  • 在这一系列事件中究竟是在哪里中断?将print 语句放在任何地方,并确认文档实际已下载,User 对象实际已初始化,数组实际循环等。在此过程中,它会打印不正确并让我们知道它在哪里.
  • @MJ-12 很棒的建议。我还将添加一个断点并逐行遍历您的代码,一路检查变量。一旦你发现一个不是你所期望的,用它是哪一行和预期值应该是什么来更新这个问题。
  • 这里的主要问题不是self.friends 期望通过重复调用fetchUserAndReturn 来填充,这也是 异步的(或者,具体来说,@987654336 @ 函数在其中)并且不会像预期的那样将User 返回到compactMap
  • 在线 self.fetchUserAndReturn 我现在收到此错误消息:“无法将类型 '()' 的值转换为关闭结果类型 'User??'”
  • @jnpdx 这可能是它。你知道如何让它工作吗?每次我得到结果时,我都尝试附加到 self.friends 数组,但它在视图中工作得很奇怪(因为每次在数据库中进行新的更改时我都必须清除 self.friends 并且因为附加到数组也就是说,每次重新加载视图都会先清除所有内容,然后用子视图填充它——看起来不太好)

标签: swift firebase google-cloud-firestore combine


【解决方案1】:

一种选择是使用 DispatchGroups 对用户的阅读进行分组,但实际上,问题中的代码并不遥远。

确实不需要 compactMap,因为用户 ID 是唯一的,同一集合中的 documentId 也是唯一的,因此不存在重复的 userUid 作为朋友的问题。

使用问题中的用户对象,这里是如何填充朋友数组

func fetchFriends(uid: String) {
    let userRef = db.collection("users").document(uid)
    userRef.addSnapshotListener { documentSnapshot, error in
        guard let user = try! documentSnapshot?.data(as: User.self) else { return }

        user.friends!.forEach( { friendUid in
            self.fetchUserAndReturn(uid: friendUid, completion: { returnedFriend in
                self.friendsArray.append(returnedFriend)
            })
        })
    }
}

func fetchUserAndReturn(uid: String, completion: @escaping ( MyUser ) -> Void ) {
    let userDocument = self.db.collection("users").document(uid)
    userDocument.getDocument(completion: { document, error in
        guard let user = try! document?.data(as: User.self) else { return }
        completion(user)
    })
}

请注意,为简洁起见,我删除了所有错误检查,因此请务必检查 Firebase 错误以及 nil 对象。

【讨论】:

    猜你喜欢
    • 2021-10-09
    • 2020-05-04
    • 1970-01-01
    • 2020-10-05
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    相关资源
    最近更新 更多