将firebase子目录从user.uid显示为Swift 3中的用户名

时间:2017-01-25 07:14:41

标签: ios swift firebase firebase-realtime-database

拥有My Profile的视图控制器。登录允许配置文件页面无错误地显示,但在注册时,按下位于视图控制器底部的联系人按钮时应用程序崩溃,如下所示。

过程:

用户注册:

func signUp(_ email: String, usersname: String, password: String, data: Data!, loginHandler: LoginHandler?) {

    FIRAuth.auth()?.createUser(withEmail: email, password: password,  completion: { (user, error) in

        if error != nil {
            // Show error to user
            self.handleFirebaseErrors(err: error as! NSError, loginHandler: loginHandler)

        } else { // success creating user

            if user?.uid != nil { // if there is a valid user id 

                // Store user to database
                self.setUserInfo(user, usersname: usersname, email: email, password: password, data: data!)

                // Log In the user
                self.login(email: email, password: password, loginHandler: loginHandler)
            }
        }
    })

}

与signUp()一样,调用setUserInfo(),其中包含图像,然后调用saveUser()

保存用户

func saveUser(_ user: FIRUser!, usersname: String, email: String, password: String) {

    // Create the user dictionary info
    let userInfo = ["email": user.email!, "password": password, "usersname": usersname, "uid": user.uid, "photoUrl": String(describing: user.photoURL!)]

    // create user reference
    let userRef = DataService.Instance.dbRef.child("riders").child(user.uid)

    // Save the user info in the database
    userRef.setValue(userInfo)

}

登录

func login(email: String, password: String, loginHandler: LoginHandler?) {

    FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user, error) in

        if error != nil {
            self.handleFirebaseErrors(err: error as! NSError, loginHandler: loginHandler)
        } else {
            loginHandler?(nil, nil)
        }
    })

}

这里的问题在saveUser()中: 目前,firebase显示了user.uid,但我希望它显示用户的用户名。

let userRef = DataService.Instance.dbRef.child("riders").child(usersname) 

使用上面的代码,一旦在RidersVC上按下联系人按钮,它就会导致应用程序崩溃,错误:

fatal error: unexpectedly found nil while unwrapping an Optional value
在MyProfileVC的第56行

let imageUrl = String(user.photoUrl)

任何想法,如何让用户名显示为“骑手”的孩子而不是user.uid而不会崩溃?任何帮助将不胜感激。

MyProfileVC.swift

if FIRAuth.auth()?.currentUser == nil {

        let vc = UIStoryboard(name: "Rider", bundle: nil).instantiateViewController(withIdentifier: "Login")
        present(vc, animated: true, completion: nil)

    } else {

        dbRef.child("riders/\(FIRAuth.auth()!.currentUser!.uid)").observe(.value, with: { (snapshot) in
            DispatchQueue.main.async(execute: {


                let user = User(snapshot: snapshot)
                self.username.text = user.usersname
                self.email.text = FIRAuth.auth()?.currentUser?.email

                let imageUrl = String(user.photoUrl)

Firebase数据库结构:(我希望如何)

{
  "riders" : {
    "rider 1" : {
      "email" : "rider1@me.com",
      "password" : "whatever",
      "photoUrl" : "https://firebasestorage.googleapis.com/...",
      "usersname" : "rider 1"
    }
  }
}

User.swift

struct User {

let usersname: String!
let email: String!
let password: String!
let photoUrl: String!
var ref: FIRDatabaseReference?
var key: String


init(snapshot: FIRDataSnapshot) {
    key = snapshot.key
    ref = snapshot.ref

    let snapshotValueUsersname = snapshot.value as? NSDictionary
    usersname = snapshotValueUsersname?["usersname"] as? String

    let snapshotValueEmail = snapshot.value as? NSDictionary
    email = snapshotValueEmail?["email"] as? String

    let snapshotValuePass = snapshot.value as? NSDictionary
    password = snapshotValuePass?["password"] as? String

    let snapshotValuePhoto = snapshot.value as? NSDictionary
    photoUrl = snapshotValuePhoto?["photoUrl"] as? String

}

Firebase结构 - (现在的方式)

{
  "drivers" : {
    "RideRequests" : {
      "europeanjunkie" : {
        "active" : true,
        "latitude" : "45.267",
        "longitude" : "-66.059",
        "userId" : "5c17ByRJljZFcM703Vqn5eSFwYJ3",
        "username" : "europeanjunkie"
      }
    }
  },

   "riders" : {
    "5c17ByRJljZFcM703Vqn5eSFwYJ3" : {
      "email" : "europeanjunkie@me.com",
      "password" : "whatever",
      "photoUrl" : "https://firebasestorage.googleapis.com",
      "uid" : "5c17ByRJljZFcM703Vqn5eSFwYJ3",
      "usersname" : "europeanjunkie"
     }
  }
}

2 个答案:

答案 0 :(得分:1)

这里有一些需要考虑的事情 - 一点点,部分或全部可能让你朝着正确的方向前进。此外,您可以删除所有DispatchQueue调用,因为Firebase会为您完成大部分繁重工作,并且使用正确的代码结构,不需要它们。

1)Swifty用户类

class UserClass {
    var usersname = ""
    var email = ""
    var password = ""
    var photoUrl = ""
    var uid = ""

    init(withSnapshot: FIRDataSnapshot) {
        let dict = withSnapshot.value as! [String:AnyObject]

        uid = withSnapshot.key
        usersname = dict["usersname"] as! String
        email = dict["email"] as! String
        password = dict["password"] as! String
        photoUrl = dict["photoUrl"] as! String
    }
}

请注意,我们正在使用每个用户的var uid来识别它们(它们的“密钥”)

与该类匹配的结构

users
  uid_0
    email: "bill@email.com"
    password: "myPassword"
    photoUrl: "http://www.url.com"
    usersname: "Bill"
  uid_1
    email: "leroy@email.com"
    password: "aPassword"
    photoUrl: "http://www.anotherUrl.com"
    usersname: "Leroy"

再次注意,用户及其相关信息存储在每个子节点的/ users节点中,该节点将用户uid作为密钥。

一些读入uid_0的代码会输出uid和name。此代码是一次性的,因此它读取uid_0,但不会将观察者附加到节点。

let userRef = rootRef.child("users/uid_0")
userRef.observeSingleEvent(of: .value, with: { snapshot in        
     let aUser = UserClass(withSnapshot: snapshot)
     print("uid \(aUser.uid)  has name  \(aUser.usersname)")
})

现在Geofire节点想要这样的东西

user_locations
  uid_0
    //geofire data
  uid_1
    //geofire data

现在,用户节点与其位置之间存在直接关联。

一般来说,最好将节点名称(键,即静态数据)与它们包含的数据取消关联,这是动态的。

根据最初问题的结构,想象一下'europeanjunkie'是否将他的名字改为'europeanjunkieDude'。然后,您引用'eurojunkie'的每个地方都必须更改 - 如果它被用作密钥,则必须读入,删除,更新和重写整个节点。

使用Firebase,uid和childByAutoId()创建的子密钥可以解决该问题。

希望有所帮助!

答案 1 :(得分:0)

在我看来,如果你想查询用户名作为关键字。构建词典有两种可能的方法。

首先,使用childByAutoId,用户名和用户ID将处于同一级别,这样您就可以获得自己喜欢的值。

{
  "riders" : {
    "-KQaU9lVcUYzIo52LgmN" : {
      "email" : "rider1@me.com",
      "password" : "whatever",
      "photoUrl" : "https://firebasestorage.googleapis.com/...",
      "usersname" : "rider 1",
      "userid" : "rider 1"
    }
  }
}

其次,让username成为骑手的孩子。但是,迈克会有很多。

{
  "riders" : {
    "username" : {
      "email" : "rider1@me.com",
      "password" : "whatever",
      "photoUrl" : "https://firebasestorage.googleapis.com/...",
      "userid" : "rider 1"
    }
  }
}