【问题标题】:How can I return an object that I create in my data service class through Firebase?如何通过 Firebase 返回我在数据服务类中创建的对象?
【发布时间】:2017-10-30 07:01:09
【问题描述】:

我正在尝试遵守 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 函数中出现意外的非 void 返回值。

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

【问题讨论】:

    标签: swift firebase model-view-controller firebase-realtime-database completionhandler


    【解决方案1】:

    您将 grabUserData function 返回值与 Firebase closure 返回值混淆了——前者是 User 但后者是 Void ;)

    你实际上是从这个闭包中返回的 — 我现在使用 explicit 返回类型来明确:

    { 
        (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
        }
    }
    

    作为最后一个参数传递给observeSingleEvent Firebase 函数。这是一个非常常见的错误;)

    完成处理程序。这里的标准模式是通过 completion handler 返回所需的User。此解决方案很好地模拟了网络请求(例如 Firebase 数据库调用)的异步性质。例如:

    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!")
        }        
    }
    

    【讨论】:

    • 只是想说声谢谢 - 我刚刚实现了它,它运行良好。 Xcode 的唯一建议是将“@escaping”添加到完成处理程序,因为它必须转义闭包。谢谢,保罗!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 2017-09-24
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    相关资源
    最近更新 更多