Swift调用Firebase getData报非void返回值错误如何解决
报错根因
Unexpected non-void return value in void function编译错误的核心原因是:getData(completion:)方法传入的回调闭包本身返回值类型为Void,你在闭包内部写return Ergebnis属于向无返回值的闭包强行返回内容,直接触发编译报错。
而且你的外层函数已经标记为async throws,完全不需要嵌套旧式的completion回调逻辑,Firebase Realtime Database本身提供了原生async/await版本的getData接口,不需要额外套Task、不需要多层闭包嵌套就能直接拿到返回值。
你原有代码还有几处问题:
- 你已经通过
as!把kurstxt强制转成了String类型,后续拼接路径时又用??设置默认值属于冗余代码,强制解包成功后变量不可能为nil - 嵌套创建Task的逻辑完全多余,
snapshot.value是同步属性,不需要加await调用 - 你在闭包里返回的
Ergebnis是Task<String, Never>类型,和函数声明要求返回的String类型不匹配,就算绕开编译错误,这个值也没法传递到外层函数。
正确实现代码
直接调用Firebase提供的async版本getData接口,和外层函数的async逻辑完全适配:
func holDaten(Daten: String) async throws -> String { let ref = Database.database().reference() // 安全解包UserDefaults里的值,避免强制解包崩溃 guard let kurstxt = UserDefaults.standard.string(forKey: "aktuellerKurs") else { return "default value" } // 直接await等待异步请求结果,不需要completion闭包 let snapshot = try await ref.child("\(kurstxt)/\(Daten)").getData() // 同步取到快照值直接返回即可 return snapshot.value as? String ?? "Unknown" }
兼容旧版本Firebase的方案
如果你使用的Firebase版本较低,没有自带async/await版本的getData接口,可以通过withCheckedThrowingContinuation手动把旧式completion接口桥接为async版本,不要尝试在异步回调里直接给外层函数返回值——回调的执行时机晚于函数本身的返回时机,就算绕开编译错误也拿不到正确结果:
func holDaten(Daten: String) async throws -> String { let ref = Database.database().reference() guard let kurstxt = UserDefaults.standard.string(forKey: "aktuellerKurs") else { return "default value" } return try await withCheckedThrowingContinuation { continuation in ref.child("\(kurstxt)/\(Daten)").getData { error, snapshot in if let error = error { continuation.resume(throwing: error) return } let result = snapshot?.value as? String ?? "Unknown" continuation.resume(returning: result) } } }
注意:尽量避免用强制解包(
as!),一旦UserDefaults中没有存储对应键的值,强制解包会直接导致应用崩溃,用guard let/if let做安全解包稳定性更高。
内容的提问来源于stack exchange,提问作者emkay
相关产品推荐
相关产品推荐

