【问题标题】:Swift3 Xcode8 - iOS app User profile data update and display in Profile Screen viewSwift3 Xcode8 - iOS 应用程序用户配置文件数据更新并显示在配置文件屏幕视图中
【发布时间】:2017-02-15 12:49:36
【问题描述】:

两周后第一次发帖和编码,请多多包涵。不断学习。

它将用户详细信息正确地保存在自己的 UID 下的 Firebase 中。我的问题是,一旦用户注销并重新登录,覆盖 func viewDidLoad() 下的代码的第二方应该获取数据库中可用的信息并将它们显示在相关的文本字段中,但它没有吨。有没有人在下面的代码中看到任何疯狂的错误?有什么解决办法吗?

(对不起,如果代码伤害了你的眼睛,我把零碎的东西四处看看)为帮助干杯。

import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase

class EditProfileTableViewController: UITableViewController {

var about = ["Name", "Email", "Phone", "Sex", "Profile Description", "Date of Birth"]
var user = FIRAuth.auth()?.currentUser?.uid
var ref = FIRDatabase.database().reference()

@IBAction func backAction(_ sender: UIBarButtonItem) {

    self.dismiss(animated: true, completion: nil)
}

@IBAction func didTappedUpdateButton(_ sender: AnyObject) {

var index = 0

    while index<about.count{

        let indexPath = NSIndexPath(row: index, section: 0)
        let cell: TextInputTableView? = self.tableView.cellForRow(at: indexPath as IndexPath) as! TextInputTableView?

        if cell?.myTextField.text != ""{

            let item:String = (cell?.myTextField.text!)!

            switch about[index]{

            case "Name":
                self.ref.child("data/users").child("\(user!)/Name").setValue(item)
            case "Email":
                self.ref.child("data/users").child("\(user!)/Email").setValue(item)
            case "Phone":
                self.ref.child("data/users").child("\(user!)/Phone").setValue(item)
            case "Sex":
                self.ref.child("data/users").child("\(user!)/Sex").setValue(item)
            case "Profile Description":
                self.ref.child("data/users").child("\(user!)/Profile Description").setValue(item)
            case "Date of Birth":
                self.ref.child("data/users").child("\(user!)/Date of Birth").setValue(item)

            default:
                print("Don't Update")
            }//end switch
        }//end if

        index+=1
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0)

    let ref = FIRDatabase.database().reference()
    ref.child("data/users").queryOrderedByKey().observe(FIRDataEventType.value, with: { (snapshot) in

        let usersDict = snapshot.value as! NSDictionary

        print(usersDict)
        let userDetails = usersDict.object(forKey: self.user!)

        var index = 0

        while index<self.about.count{

            let indexPath = NSIndexPath(row: index, section:0)
            let cell : TextInputTableView? = self.tableView.cellForRow(at: indexPath as IndexPath) as! TextInputTableView?

            let field: String = (cell?.myTextField.placeholder?.lowercased() )!

                switch field
                {
        case "Name":
        cell?.configure(text: (userDetails as AnyObject).object(forKey: "Name") as? String, placeholder: "Name")
        case "Email":
        cell?.configure(text: (userDetails as AnyObject).object(forKey: "Email") as? String, placeholder: "Email")
        case "Phone":
        cell?.configure(text: (userDetails as AnyObject).object(forKey: "Phone") as? String, placeholder: "Phone")
        case "Sex":
        cell?.configure(text: (userDetails as AnyObject).object(forKey: "Sex") as? String, placeholder: "Sex")
        case "Profile Description":
        cell?.configure(text: (userDetails as AnyObject).object(forKey: "Profile Description") as? String, placeholder: "Profile Description")
        case "Date of Birth":
        cell?.configure(text: (userDetails as AnyObject).object(forKey: "Date of Birth") as? String, placeholder: "Date of Birth")

                default:
                    print("")

                }//end switch

            index+=1
        }
    })
}

override func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return about.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell  {

    let cell: TextInputTableView = tableView.dequeueReusableCell(withIdentifier: "TextInput", for: indexPath) as! TextInputTableView

    cell.configure(text: "", placeholder: "\(about[indexPath.row])")

    return cell
}

【问题讨论】:

  • 有没有报错?你有没有试过打印出usersDict 的值
  • 没有错误,它只是不起作用,但似乎打印的值是针对所有用户的,它似乎没有打印当前用户的那个......(帽子将是我猜有数千万用户的问题:))感谢您查看@EmilDavid!
  • 别担心,伙计..你能发布你的数据库结构吗?因为我感觉你当前的查询并没有完全按照你的想法做
  • APP NAME ...data ...users(这是与 Firebase 控制台中的 Auth 选项卡类似的 UID)-字段-字段-字段显然我不够资深,无法在我的问题所以他们创建了一个链接i.stack.imgur.com/yYkWk.png我搞砸了数据库结构吗? @EmilDavid
  • 请为我澄清这两件事。您的结构是 ap​​pname/data/user/uid。进入 uid 后,您会获得有关该特定用户的详细信息,对吗?你想提取当前登录用户的详细信息吗?

标签: ios firebase firebase-realtime-database swift3 xcode8


【解决方案1】:

对不起,沉默。我离开了我的笔记本电脑。这些是我的建议。

  1. 摆脱数据节点;这似乎是多余的。您可以简单地在根节点下添加其他节点,即 appname.

  2. 折射你的viewDidLoad;因为它相当复杂。将 firebase 检索内容放在单独的方法中。

  3. 养成重复使用的习惯。它使您的代码不那么复杂且易于遵循。这甚至适用于像变量一样少的东西。例如您已在全球范围内声明了 ref;这是要走的路。但是你又在你的viewDidLoad 中声明了另一个ref,它们都有相同的目的。我知道这是一件小事,但为什么有多个变量服务于同一目的?

  4. 您没有检查结果是否有任何错误或nil 值。你直接拆开东西。直接打开包装很好,但这只能在您 100% 确定您确实有价值的地方进行。对于大多数互联网查询,情况并非如此,您希望您的应用也能处理这些情况。

如果我是你,我会这样做。 我做了这两个全局变量:

var currentUser: FIRUser = FIRUser()
let databaseRef = FIRDatabase.database().reference()

然后我做了这个方法,它只获取一次用户数据。如果您希望它获得实时更新,则只需将其从 observeSingleEvent 更改为 observe,并将类型更改为 .childAdded.childChanged,具体取决于您的具体情况。我会把这个挑战留给你,其他一切都差不多。

func getUserDetailsOnce()
{
    self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0)

    // check first if the user is currently logged in. If yes, then save them in the variable user. Normally, you'd want to run this check inside your AppDelegate after didFinishLaunchWithOptions
    guard let user = FIRAuth.auth()?.currentUser else
    {
        print("No logged user in existence")
        return
    }

    currentUser = user // update the global variable

    // append to the current user's node location
    databaseRef.child("data/users").child(currentUser.uid).observeSingleEvent(of: .value) { (snapshot: FIRDataSnapshot) in

        // you have retrieved the result and store it in firebaseValue. snapshot.value returns AnyObject?. Since its an optional it can be nil and we want to handle that scenario. And its highly advisable to cast it as a [String:AnyObject] instead of an NSDictionary
        guard let firebaseValue = snapshot.value as [String:AnyObject] else
        {
            print("Error with FrB snapshot") // this is printed if no Firebase value is returned
            return
        }

        // Now that we have our value, we can access the respective elements

        let index = 0

        while index < self.about.count
        {
            let indexPath = NSIndexPath(row: index, section: 0)
            let cell: UITableViewCell = self.tableView.cellForRow(at: indexPath)

            // This is where I am a little bit puzzled as to how you have your cell structured. But if you want to access the individual elements inisde our database then you simply have to check for nils for each individual component as shown below

            guard let email = firebaseValue["email"] as? String, let name = firebaseValue["name"] as? String else // add the other ones respectively
            {
                print("Error extracting individual Firebase components")
                return
            }

            // Then you can display the values since they are now stored in the variables email,name etc

            index += 1
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    • 1970-01-01
    相关资源
    最近更新 更多