Firebase Swift中如何获取指定UID用户数据及当前用户好友数据?
我来帮你解决这两个Firebase Swift开发中的问题,分两部分详细讲解:
一、获取特定UID用户的数据
不管你用的是Firebase Realtime Database还是Firestore,核心逻辑都是通过用户UID直接定位到对应的数据源节点/文档,然后读取数据。
1. 针对Realtime Database的实现
假设你的用户数据存在users节点下,每个用户的UID作为节点key,结构如下:
users |- {userUID1} |- name: "张三" |- email: "zhangsan@example.com" |- {userUID2} |- name: "李四" |- email: "lisi@example.com"
代码示例:
import FirebaseDatabase // 替换成你要查询的目标用户UID let targetUserUID = "your-target-user-uid" let userRef = Database.database().reference().child("users").child(targetUserUID) // 单次读取数据(如果需要实时监听变化,把observeSingleEvent改成observe) userRef.observeSingleEvent(of: .value) { snapshot in guard let userData = snapshot.value as? [String: Any] else { print("未找到该用户的数据") return } // 解析数据,这里可以转成自定义的User模型类/结构体 let userName = userData["name"] as? String ?? "匿名用户" let userEmail = userData["email"] as? String ?? "" print("获取到用户信息:\(userName) - \(userEmail)") }
2. 针对Firestore的实现
如果用Firestore,用户数据存在users集合中,每个文档ID就是用户UID,代码逻辑类似:
import FirebaseFirestore let targetUserUID = "your-target-user-uid" let db = Firestore.firestore() db.collection("users").document(targetUserUID).getDocument { document, error in if let error = error { print("获取用户数据失败:\(error.localizedDescription)") return } guard let document = document, document.exists else { print("该用户文档不存在") return } // 解析数据 let userData = document.data() let userName = userData?["name"] as? String ?? "匿名用户" let userEmail = userData?["email"] as? String ?? "" print("获取到用户信息:\(userName) - \(userEmail)") }
二、获取当前用户的联系人(friends)数据并适配TableView
虽然你提到的存储结构图片没法看到,但我会基于最常见的两种存储场景来讲解,你可以根据自己的实际结构调整。
场景1:Realtime Database中friends节点存储关联UID(键值对形式)
假设结构如下(当前用户的friends节点下,每个key是联系人的UID,值为true标记关联):
users |- {currentUserUID} |- friends |- {friendUID1}: true |- {friendUID2}: true
实现步骤:
- 确认用户已登录,获取当前用户UID
- 读取当前用户的friends节点,拿到所有联系人UID
- 批量获取每个联系人的详细数据
- 存储到数组中,刷新TableView
代码示例(包含TableView适配):
import FirebaseAuth import FirebaseDatabase // 自定义用户模型,方便TableView展示数据 struct Friend { let uid: String let name: String let email: String } class FriendsListVC: UIViewController, UITableViewDataSource { @IBOutlet weak var friendsTableView: UITableView! private var friendsArray: [Friend] = [] override func viewDidLoad() { super.viewDidLoad() friendsTableView.dataSource = self // 注册TableViewCell(如果是storyboard中设置了identifier可以跳过) friendsTableView.register(UITableViewCell.self, forCellReuseIdentifier: "FriendCell") fetchFriendsData() } private func fetchFriendsData() { guard let currentUID = Auth.auth().currentUser?.uid else { print("用户未登录,请先登录") return } // 读取当前用户的联系人UID列表 let friendsRef = Database.database().reference().child("users").child(currentUID).child("friends") friendsRef.observeSingleEvent(of: .value) { [weak self] snapshot in guard let friendUIDs = snapshot.value as? [String: Bool] else { print("当前用户暂无联系人") return } self?.friendsArray.removeAll() let dispatchGroup = DispatchGroup() // 用于批量处理请求,避免多次刷新TableView for (friendUID, _) in friendUIDs { dispatchGroup.enter() // 获取单个联系人的详细数据 let userRef = Database.database().reference().child("users").child(friendUID) userRef.observeSingleEvent(of: .value) { snapshot in defer { dispatchGroup.leave() } // 不管成功失败都标记任务完成 guard let userData = snapshot.value as? [String: Any], let name = userData["name"] as? String, let email = userData["email"] as? String else { return } let friend = Friend(uid: friendUID, name: name, email: email) self?.friendsArray.append(friend) } } // 所有请求完成后,在主线程刷新TableView dispatchGroup.notify(queue: .main) { self?.friendsTableView.reloadData() } } } // MARK: - UITableView DataSource func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return friendsArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "FriendCell", for: indexPath) let friend = friendsArray[indexPath.row] cell.textLabel?.text = friend.name cell.detailTextLabel?.text = friend.email return cell } }
场景2:Firestore中friends字段是UID数组
假设Firestore的users集合中,当前用户文档有一个friends数组字段,存储所有联系人的UID:
users/{currentUID} |- name: "当前用户名称" |- friends: ["friendUID1", "friendUID2"]
实现步骤:
- 获取当前用户文档,读取
friends数组 - 批量查询这些UID对应的用户文档
- 解析数据到数组,刷新TableView
代码示例:
import FirebaseAuth import FirebaseFirestore struct Friend { let uid: String let name: String let email: String } class FriendsListVC: UIViewController, UITableViewDataSource { @IBOutlet weak var friendsTableView: UITableView! private var friendsArray: [Friend] = [] private let db = Firestore.firestore() override func viewDidLoad() { super.viewDidLoad() friendsTableView.dataSource = self friendsTableView.register(UITableViewCell.self, forCellReuseIdentifier: "FriendCell") fetchFriendsData() } private func fetchFriendsData() { guard let currentUID = Auth.auth().currentUser?.uid else { print("用户未登录,请先登录") return } // 获取当前用户的联系人UID数组 db.collection("users").document(currentUID).getDocument { [weak self] document, error in if let error = error { print("获取联系人列表失败:\(error.localizedDescription)") return } guard let document = document, document.exists, let friendUIDs = document["friends"] as? [String] else { print("当前用户暂无联系人") return } // 批量查询所有联系人的文档 self?.db.collection("users") .whereField(FieldPath.documentID(), in: friendUIDs) .getDocuments { querySnapshot, error in if let error = error { print("获取联系人数据失败:\(error.localizedDescription)") return } guard let documents = querySnapshot?.documents else { print("未找到联系人数据") return } // 解析数据到数组 self?.friendsArray = documents.compactMap { doc in guard let name = doc["name"] as? String, let email = doc["email"] as? String else { return nil } return Friend(uid: doc.documentID, name: name, email: email) } // 主线程刷新TableView DispatchQueue.main.async { self?.friendsTableView.reloadData() } } } } // MARK: - UITableView DataSource func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return friendsArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "FriendCell", for: indexPath) let friend = friendsArray[indexPath.row] cell.textLabel?.text = friend.name cell.detailTextLabel?.text = friend.email return cell } }
补充提示
如果你的friends存储结构和上面两种都不同,比如是嵌套对象或者其他形式,可以把具体的数据库结构(JSON或截图描述)提供出来,我可以帮你调整查询逻辑。另外,一定要确保Firebase的安全规则设置正确,允许用户读取自己的friends数据,以及其他用户的公开信息(比如name、email)。
内容的提问来源于stack exchange,提问作者Jude Molloy
相关产品推荐
相关产品推荐

