Как определить вторичное значение, если значение Firebase равно нулю - PullRequest
0 голосов
/ 28 апреля 2018

В моем приложении есть функция, которая используется для возврата электронной почты, но, конечно, мои бета-тестеры хотели бы, чтобы я использовал имя пользователя, а не делал его электронную почту публичной. Проблема в том, что не все пользователи определили имя пользователя. Я могу изменить дочерний путь, но приложение вылетает для всех, когда они сталкиваются с пользователем, который не вводил имя пользователя при регистрации. Хотя я захочу изменить это позже, это кажется хорошим упражнением: как получить вторичное значение, если запрошенное значение равно нулю?

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

1 Ответ

0 голосов
/ 29 апреля 2018

Эта строка вызывает ошибку:

handler(user.childSnapshot(forPath: "username").value as! String)

Причина в том, что с помощью оператора взрыва ! ваша сила развернула его и применила в качестве строки здесь: as! String. Проблема в том, что если там ничего нет и возвращается значение nil, вы не можете разыграть nil как String.

например. это то, что он видит, когда возвращается значение nil:

handler(user.childSnapshot(forPath: "username").value as! String)
// since user.childSnapshot(forPath: "username").value == nil it sees
handler(nil as! String)

Главное, что нужно понять, это то, что путем принудительного распаковывания чего-либо, используя ! ваше изречение, что, что бы это ни было, это определенно не nil. Таким образом, когда он равен nil , тогда произойдет крах . Если вы не уверены в том, что вернется, вам следует использовать ? и безопасно развернуть его с помощью необязательного связывания if let, оператора guard или оператора объединения нулей ??, как описано ниже

Вы должны использовать Optional внутри вашего обработчика, чтобы он мог принимать ноль.

Попробуйте это.

Сделайте так, чтобы ваш обработчик мог принять Optional типа String:

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? поэтому он может принимать необязательный тип String. Я изменил это с:

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

до:

func getUsername(forUID uid: String, handler: @escaping (_ username: String?) -> 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)")
                    }
                }
            }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...