将firebase子项从user.uid显示到Swift 3中的用户名 [英] displaying firebase child from user.uid to username in Swift 3

查看:128
本文介绍了将firebase子项从user.uid显示到Swift 3中的用户名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Have a view controller for My Profile. Logging in allows the profile page to appear without errors but when signing up, app crashes when pressing the contacts button located at bottom of view controller as seen below.

流程:

用户注册:

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

As in the signUp(), setUserInfo() is called, which contains images, and then calls 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,但我想要它显示用户的用户名。

The problem here is in saveUser(): At the moment, firebase shows the user.uid but I want it to show the username of the user.

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

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

With the above code, once the contacts button is pressed on the RidersVC, it crashes the app with error:

fatal error: unexpectedly found nil while unwrapping an Optional value

$ b MyProfileVC第56行
$ b

on line 56 of MyProfileVC:

let imageUrl = String(user.photoUrl)

我是如何将用户名显示为骑手的孩子而不是用户的任何想法。没有它崩溃?任何帮助将不胜感激。

Any ideas as how I can get the username to be displayed as the child of "riders" instead of the user.uid without it crashing? Any help would be appreciated.

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数据库结构:(我希望如何)

Firebase Database Structure: (how I want it to be)

{
  "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结构 - (现在的方式)

Firebase structure - (the way it is now)

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


推荐答案

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

Here's some stuff to consider - a little, some or all may get you headed in the right direction. Also, you can probably remove all of the DispatchQueue calls as Firebase does most of the heavy lifting for you, and with proper code structure, they are not needed.

1)一个Swifty用户类

1) A Swifty user class

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用户识别它们(它们的'键')

note that we are using the var uid of each user to identify them (their 'key')

与该类匹配的结构

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作为键。

Notice again the users and their associated info are stored within the /users node in each child node that has that users uid as the key.

并且一些读入uid_0的代码打印uid和名称。此代码是一次性的,因此它读取uid_0,但不会将观察者附加到节点。

And some code that reads in uid_0, prints the uid and name. This code is a one-shot so it reads uid_0, but does NOT leave an observer attached to the node.

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节点想要这样的东西

Now the Geofire node would like something like this

user_locations
  uid_0
    //geofire data
  uid_1
    //geofire data

所以现在之间存在直接关联用户节点及其位置。

So now there is a direct correlation between the users node and their location.

通常,将节点名称(密钥,即静态数据)与其包含的数据(动态)取消关联是个好主意。

In general, it's a good idea to disassociate node names (keys, which are static data) from the data they contain, which is dynamic.

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

With the structure in the initial question, imagine if 'europeanjunkie' changed his name to 'europeanjunkieDude'. Every place you reference 'europeanjunkie' would then have to be changed - and if it's used as a key, the entire node would have to be read in, deleted, updated, and re-written.

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

Using child keys created by Firebase, uid's and childByAutoId(), removes that issue.

希望有所帮助!

这篇关于将firebase子项从user.uid显示到Swift 3中的用户名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆