2017-01-25 13 views
0

マイプロフィール用のビューコントローラがあります。ログインするとプロファイルページがエラーなく表示されますが、サインアップすると、下に示すようにView Controllerの下部にある連絡先ボタンを押すとアプリがクラッシュします。firebaseの子を表示するuser.uidからSwiftのユーザ名3

プロセス:

ユーザサインアップ:サインアップ()のよう

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

} 

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

} 

ここでの問題は、saveUser()である

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

} 

でログ:現時点では 、firebaseはuser.uidを示していますが、私はそれがユーザーのユーザー名を表示したいです。上記のコードで

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

コンタクトボタンがRidersVCに押圧されると、それはエラーでアプリケーションがクラッシュ:MyProfileVCのライン56上の

fatal error: unexpectedly found nil while unwrapping an Optional value 

を:

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" : "[email protected]", 
     "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" : "[email protected]", 
     "password" : "whatever", 
     "photoUrl" : "https://firebasestorage.googleapis.com", 
     "uid" : "5c17ByRJljZFcM703Vqn5eSFwYJ3", 
     "usersname" : "europeanjunkie" 
    } 
    } 
} 
+0

データベースのデータ構造を変更する必要があります。あなたはライダーの子を 'uid'(' userRef = DataService.Instance.dbRef.child( "riders")。child(user.uid) ')として保存します。しかし、ライダーの子供を 'username'(' DataService.Instance.dbRef.child( "riders")。child(usersname) ')として取得したいとします。絶対に、それは無です。 – WeiJay

+0

このコードにはいくつかの問題がありますが、最も重要なのはUserクラス内のスナップショットで何が行われているかです。 Firebase構造とUserクラスのスニペットを投稿してください。答えは簡単ですが、まずそれを見る必要があります。 – Jay

+0

@JayがUser.swiftとFirebaseの構造体を追加しました – LizG

答えて

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: "[email protected]" 
    password: "myPassword" 
    photoUrl: "http://www.url.com" 
    usersname: "Bill" 
    uid_1 
    email: "[email protected]" 
    password: "aPassword" 
    photoUrl: "http://www.anotherUrl.com" 
    usersname: "Leroy" 

再度、ユーザーとその関連情報は、そのユーザーuidをキーとして持つ各子ノードの/ usersノードに格納されています。

そして、uid_0で読み取るコードの中には、uidと名前が表示されます。このコードはワンショットなので、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'に名前を変更した場合を想像してください。 「europeanjunkie」を参照する場所はすべて変更する必要があります。キーとして使用する場合は、ノード全体を読み込み、削除し、更新し、書き直す必要があります。

Firebaseで作成された子キーを使用すると、uidとchildByAutoId()はその問題を削除します。

希望に役立ちます!

0

私の意見では、ユーザ名をキーワードとして質問したいと思っています。辞書を構造化するには2通りの方法があります。

最初に、childByAutoIdを使用すると、usernameとuseridは同じレベルになりますので、好きな値を取得できます。

{ 
    "riders" : { 
    "-KQaU9lVcUYzIo52LgmN" : { 
     "email" : "[email protected]", 
     "password" : "whatever", 
     "photoUrl" : "https://firebasestorage.googleapis.com/...", 
     "usersname" : "rider 1", 
     "userid" : "rider 1" 
    } 
    } 
} 

次に、usernameをライダーの子として作成します。しかし、マイクがたくさんあるだろう。

{ 
    "riders" : { 
    "username" : { 
     "email" : "[email protected]", 
     "password" : "whatever", 
     "photoUrl" : "https://firebasestorage.googleapis.com/...", 
     "userid" : "rider 1" 
    } 
    } 
} 
+0

.child(user.uid)以外の方法で実行しようとすると、ユーザーにログインしていないためアプリケーションがクラッシュします。 – LizG

関連する問題