Ios 如果Firebase值为零,如何定义辅助值

Ios 如果Firebase值为零,如何定义辅助值,ios,firebase,Ios,Firebase,在我的应用程序中,我有一个用于返回电子邮件的功能,但我的测试人员当然希望我使用用户名,而不是公开他们的电子邮件。问题是,并非所有用户都定义了用户名。我可以切换子路径,但每当遇到注册时没有输入用户名的用户时,每个人的应用程序都会崩溃。虽然稍后我将要更改此设置,但这似乎是一个很好的练习:如果请求的值为nil,如何获取辅助值 func getUsername(forUID uid: String, handler: @escaping (_ username: String) -> ()) {

在我的应用程序中,我有一个用于返回电子邮件的功能,但我的测试人员当然希望我使用用户名,而不是公开他们的电子邮件。问题是,并非所有用户都定义了用户名。我可以切换子路径,但每当遇到注册时没有输入用户名的用户时,每个人的应用程序都会崩溃。虽然稍后我将要更改此设置,但这似乎是一个很好的练习:如果请求的值为nil,如何获取辅助值

func getUsername(forUID uid: String, handler: @escaping (_ username: String) -> ()) {
        REF_USERS.observeSingleEvent(of: .value) { (userSnapshot) in
            guard let userSnapshot = userSnapshot.children.allObjects as? [DataSnapshot] else { return }
            for user in userSnapshot {
                if user.key == uid {
                    handler(user.childSnapshot(forPath: "username").value as! String)
                }
            }

这一行是导致撞车的原因:

handler(user.childSnapshot(forPath: "username").value as! String)
原因是使用了bang运算符
你的原力将其展开并在此处将其转换为字符串:
as!字符串
。问题是如果那里没有任何内容,并且返回了
nil
值,则不能将
nil
转换为
字符串

这是当返回一个nil值时它所看到的:

handler(user.childSnapshot(forPath: "username").value as! String)
// since user.childSnapshot(forPath: "username").value == nil it sees
handler(nil as! String)
主要要理解的是,通过使用
强制展开某个东西
你说不管是什么,绝对不是
nil
。因此,当它为零时,将出现崩溃。如果您不确定将返回什么,则应使用
并使用可选绑定
(如果let
)、
保护
语句或无合并运算符
安全地打开包装,如下所述

您必须在处理程序中使用
可选的
,以便它可以接受nil

试试这个

使处理程序可以接受字符串类型的可选值:

handler: @escaping (_ username: String?) // the question mark after the String makes it optional
然后,当调用处理程序时,如果用户名为nil,则使用nil合并运算符
提供默认值:

handler(user.childSnapshot(forPath: "username").value as? String ?? "defaultValue")
这是您的代码:

func getUsername(forUID uid: String, handler: @escaping (_ username: String?) -> ()) {
        REF_USERS.observeSingleEvent(of: .value) { (userSnapshot) in
            guard let userSnapshot = userSnapshot.children.allObjects as? [DataSnapshot] else { return }
            for user in userSnapshot {
                if user.key == uid {
                    handler(user.childSnapshot(forPath: "username").value as? String ?? "defaultValue")
                }
            }
下面是对你问题的回答。在处理程序中,我将返回类型从()更改为String?因此,它可以接受可选的字符串类型。我把它改成:

func getUsername(forUID uid: String, handler: @escaping (_ username: String?) -> () {
致:

试试这个:

func getUsername(forUID uid: String, handler: @escaping (_ username: String?) -> String?) {
        REF_USERS.observeSingleEvent(of: .value) { (userSnapshot) in
            guard let userSnapshot = userSnapshot.children.allObjects as? [DataSnapshot] else { return }
            for user in userSnapshot {
                if user.key == uid {

                    // 1. you no longer use the nil coalescing operator because if you use it then you can't get a nil value
                    // 2. declare a local variable and name it value of Optional type String meaning it will accept nil or a String
                    var value: String? = handler(user.childSnapshot(forPath: "username").value as? String)
                    print("+++++value is: \(value ?? "value is nil")")                            

                    // 3. run a check on the value. If value is == nil then try your other node but you should probably use the nil coalescing operator there
                    // if value != nil which means username above returned a value other then nil then this won't run
                    if value == nil {
                       print("the username node was nil so use this different node")
                       value = handler(user.childSnapshot(forPath: "theDifferentNode").value as? String ?? "someDefaultValue") // if for some reason this is nil then this will have some default value
                       print("-----value is now: \(value)")
                    }
                }
            }

你能再解释一下吗?我正在我的应用程序中做类似的事情,以便我能够帮助您。我不确定的是at在哪里坠毁?如果他们没有输入用户名,它会崩溃吗?或者在firebase查找用户名但用户名不存在后它会崩溃吗?您需要添加更多代码。并准确显示崩溃发生的位置,或提取或设置nil值Firebase查找用户名时崩溃发生,错误记录为无法将“NSNull”(0x10c7ee850)类型的值转换为“NSString”(0x10b9672a8)。这里的想法是,有一个“用户”节点有时有名称,还有一个“概要文件”节点也包含名称。我想知道如果第一个位置为零或不存在,是否有办法让firebase搜索第二个位置。当然,如果两者都不存在,它应该使用默认值,或者在不崩溃的情况下继续。我是swift新手,所以不要害怕指出明显的问题。使用默认值谢谢!这就解决了崩溃问题,你的解释真的让我明白了前进的方向。现在它将在nil值之后继续存在,如果值为nil,我是否可以构造一个if/else语句来使用另一个节点?如果我添加到底部工作表中的其他答案有效,请告诉我。这是非常好的,我得到了在firebase发生的事情。我得到一个错误,thoug的值变量行:无法将“()”类型的值转换为指定的“字符串”类型。这是我的错误,我只是注意到它是一个不返回任何内容的函数,这就是出现错误的原因。当您创建处理程序时,您创建了一个闭包,该闭包接受可选类型的字符串参数,但不返回任何内容:(uu用户名:字符串?)->()。当我创建值时,我将其设置为字符串类型的可选值,但问题是您的处理程序没有返回任何内容,因此2不匹配,您明白吗?我必须更改代码,我将删除我为该部分编写的内容,我将尝试想想办法。保持你的评论。它会帮助你了解我最初写的作品。我试过了,它对我有用,所以它对你也有用。试试看,如果你有什么问题就告诉我
func getUsername(forUID uid: String, handler: @escaping (_ username: String?) -> String?) {
        REF_USERS.observeSingleEvent(of: .value) { (userSnapshot) in
            guard let userSnapshot = userSnapshot.children.allObjects as? [DataSnapshot] else { return }
            for user in userSnapshot {
                if user.key == uid {

                    // 1. you no longer use the nil coalescing operator because if you use it then you can't get a nil value
                    // 2. declare a local variable and name it value of Optional type String meaning it will accept nil or a String
                    var value: String? = handler(user.childSnapshot(forPath: "username").value as? String)
                    print("+++++value is: \(value ?? "value is nil")")                            

                    // 3. run a check on the value. If value is == nil then try your other node but you should probably use the nil coalescing operator there
                    // if value != nil which means username above returned a value other then nil then this won't run
                    if value == nil {
                       print("the username node was nil so use this different node")
                       value = handler(user.childSnapshot(forPath: "theDifferentNode").value as? String ?? "someDefaultValue") // if for some reason this is nil then this will have some default value
                       print("-----value is now: \(value)")
                    }
                }
            }