一尘不染

如何通过Firebase返回在数据服务类中创建的对象?

swift

我试图遵守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函数中非预期的非无效返回值。

但是该功能显然不是无效的。那我该怎么办?


阅读 227

收藏
2020-07-07

共1个答案

一尘不染

您正在将grabUserData 函数 返回值与Firebase 闭包 返回值混淆-前者是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函数。这是一个 非常 常见的错误;)

完成处理程序 。这里的标准模式是通过 完成处理程序 返回 所需的内容。该解决方案很好地模拟了网络请求(例如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!")
    }        
}
2020-07-07