Firebase实时数据库获取userImage字符串传递问题求助
Firebase实时数据库异步获取userImage无法return的问题解决
在从Firebase实时数据库请求获取字符串userImage时,无法直接用return返回该值,系统提示错误:Unexpected non-void return value in void function,需要将userImage作为参数传入importComment对象中,相关代码如下:
func datenBankAbfrage() { print("datenbankabfrage getriggert") dic = [:] for name in myFeed.myArray1[0..<myFeed.myArray1.count] { ref = Database.database().reference().child("placeID/\(name)") ref.observe(.value) { (snapshot) in self.dic[name] = [] var specificNameVideos = [importComment]() for video in snapshot.children.allObjects as! [DataSnapshot] { let Object1 = video.value as? [String: AnyObject] let timestampDate = NSDate(timeIntervalSince1970: Double(Object1?["userTime"] as! NSNumber)/1000) let dateFormatter = DateFormatter() dateFormatter.timeZone = NSTimeZone.local dateFormatter.dateFormat = "dd.MM.YY hh:mm" let time = dateFormatter.string(from: timestampDate as Date) print(time + "Uhr") let userName = Object1?["userName"] ... let kommentarCount = Object1?["kommentarCount"] let userID = Object1?["userID"] //print(userID!) ViewComments.commentIDNew = commentId as! String func wertBerechnen(completion: @escaping (String) -> Void) { self.ref = Database.database().reference() self.ref.child("user/\(userID!)").observeSingleEvent (of: .value, with: { (snapshot) in let value = snapshot.value as? NSDictionary let userImage = value?["picture"] as? String ?? "" completion(userImage) }) } wertBerechnen { userImage in let video = importComment( userName: userName as! String, userGroup: userGroup as! String, userComment: userComment as! String, userTime: userTime as! String, userLikes: userLikes as! Int, commentId: commentId as! String, placeID: placeID as! String, kommentarCount: kommentarCount as? Int, userImage: userImage) specificNameVideos.append(video) } } self.dic[name] = specificNameVideos let tem = Array(self.dic.values).flatMap { $0 } // You can also sort allComments with userTime property self.table = tem.sorted { $0.userTime! > $1.userTime! } self.tableView.reloadData() } myFeed.myArray1 = [] } }
问题分析
这个错误的核心是Firebase的数据库查询属于异步操作,observeSingleEvent的回调闭包是void类型,根本不允许用return返回值。你已经想到用completion回调来传递userImage,这个思路是对的,但当前代码存在时序问题:循环遍历子节点时,异步请求还没完成,就执行了self.dic[name] = specificNameVideos和表格刷新,导致specificNameVideos里的数据不完整。另外,代码里大量使用强制解包(!),很容易触发崩溃,需要优化。
修正方案
下面是调整后的代码,解决异步时序问题并优化稳定性:
func datenBankAbfrage() { print("datenbankabfrage getriggert") dic = [:] for name in myFeed.myArray1 { ref = Database.database().reference().child("placeID/\(name)") ref.observe(.value) { [weak self] snapshot in guard let self = self else { return } self.dic[name] = [] var specificNameVideos = [importComment]() let dispatchGroup = DispatchGroup() for video in snapshot.children.allObjects as! [DataSnapshot] { // 用可选绑定替代强制解包,避免崩溃 guard let object1 = video.value as? [String: Any], let userTimeNum = object1["userTime"] as? NSNumber, let userName = object1["userName"] as? String, let userGroup = object1["userGroup"] as? String, let userComment = object1["userComment"] as? String, let userLikes = object1["userLikes"] as? Int, let commentId = object1["commentId"] as? String, let placeID = object1["placeID"] as? String, let userID = object1["userID"] as? String else { continue } // 时间格式处理,改用Swift原生Date类型 let timestampDate = Date(timeIntervalSince1970: Double(userTimeNum)/1000) let dateFormatter = DateFormatter() dateFormatter.timeZone = .current dateFormatter.dateFormat = "dd.MM.YY hh:mm" let time = dateFormatter.string(from: timestampDate) print("\(time) Uhr") ViewComments.commentIDNew = commentId dispatchGroup.enter() // 调用外部定义的异步函数 self.fetchUserImage(userID: userID) { userImage in let kommentarCount = object1["kommentarCount"] as? Int let videoModel = importComment( userName: userName, userGroup: userGroup, userComment: userComment, userTime: time, userLikes: userLikes, commentId: commentId, placeID: placeID, kommentarCount: kommentarCount, userImage: userImage ) specificNameVideos.append(videoModel) dispatchGroup.leave() } } // 所有异步请求完成后再更新数据和刷新表格 dispatchGroup.notify(queue: .main) { self.dic[name] = specificNameVideos let tem = Array(self.dic.values).flatMap { $0 } self.table = tem.sorted { $0.userTime ?? "" > $1.userTime ?? "" } self.tableView.reloadData() } } } myFeed.myArray1 = [] } // 将获取用户头像的逻辑独立成外部函数,避免重复定义 private func fetchUserImage(userID: String, completion: @escaping (String) -> Void) { let userRef = Database.database().reference().child("user/\(userID)") userRef.observeSingleEvent(of: .value) { snapshot in let userData = snapshot.value as? [String: Any] let userImage = userData?["picture"] as? String ?? "" completion(userImage) } }
关键优化点
- 异步时序控制:用
DispatchGroup跟踪所有获取userImage的异步请求,确保所有数据都加载完成后再更新字典和刷新表格; - 避免循环引用:在闭包中使用
[weak self]和guard let self = self,防止内存泄漏; - 稳定性提升:用可选绑定替代强制解包,避免因数据缺失导致的崩溃;
- 代码结构优化:将获取用户头像的逻辑独立成外部函数,避免在循环中重复定义函数,提升代码可读性;
- 现代Swift语法:替换
NSDate、NSTimeZone为Swift原生的Date和TimeZone,符合现代开发规范。
内容的提问来源于stack exchange,提问作者submariner
相关产品推荐
相关产品推荐

