Swift3 Xcode8 - iOS应用用户配置文件数据更新并显示在配置文件屏幕视图中

时间:2016-10-06 16:56:02

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

首次发布和编码2周后,请放纵。在学习中学习。

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

(对不起,如果代码伤到了你的眼睛,我就会点点滴滴)干杯帮忙。

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
}

enter image description here

1 个答案:

答案 0 :(得分:0)

抱歉沉默。我离开了笔记本电脑。这些是我的建议。

  1. 摆脱数据节点;这似乎相当多余。您只需在根节点下添加其他节点,即 appname

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

  3. 采用重复使用的习惯。它使您的代码不那么复杂,易于理解。这甚至适用于变量这一点。例如你在全球范围内宣布了ref;这是要走的路。但是,您再次在ref中声明了另一个viewDidLoad,它们都用于同一目的。我知道它是一个小问题,但为什么有多个变量用于相同的目的?

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

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

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