我试图遵守MVC惯例,并将所有网络代码保留在我的应用程序中使用的数据服务类中。在一个屏幕上,我有需要显示的用户名和用户名。更新此函数时,我正在调用此函数:
func grabUserData() -> User { REF_USERS.child(getCurrentUID()).observeSingleEvent(of: .value) { (snapshot) in if let userDict = snapshot.value as? Dictionary<String, String> { let user = User( first: userDict["firstName"]!, last: userDict["lastName"]!, username: userDict["username"]! ) return user } } }
但是尝试返回用户时出现错误!它说:
void函数中非预期的非无效返回值。
但是该功能显然不是无效的。那我该怎么办?
您正在将grabUserData 函数 返回值与Firebase 闭包 返回值混淆-前者是User但后者是Void;)
grabUserData
User
Void
您实际上是从此关闭返回的—我现在使用一个 明确的 返回类型来明确说明:
{ (snapshot) -> Void in if let userDict = snapshot.value as? Dictionary<String,String> { let user = User( first: userDict["firstName"]!, last: userDict["lastName"]!, username: userDict["username"]! ) return user } }
将其作为最后一个参数传递给observeSingleEventFirebase函数。这是一个 非常 常见的错误;)
observeSingleEvent
完成处理程序 。这里的标准模式是通过 完成处理程序 返回 所需的内容。该解决方案很好地模拟了网络请求(例如Firebase数据库调用)的 异步 性质。例如:User
func grabUserData(completion: @escaping (User?) -> Void) { REF_USERS.child(getCurrentUID()).observeSingleEvent(of: .value) { (snapshot) in if let userDict = snapshot.value as? Dictionary<String, String> { let user = User( first: userDict["firstName"]!, last: userDict["lastName"]!, username: userDict["username"]! ) completion(user) // Returns user! } else { completion(nil) // User not found! } } }
最后,在数据服务 客户端代码中 ,像这样调用它:
grabUserData() { (user) in if let user = user { print("Grabbed user: \(user)") } else { print("User not found!") } }