如何使用动态单元格获取UITableView中多个textField的值?

时间:2017-11-17 16:49:54

标签: ios swift uitableview

在UIViewController中,我有一个UITableView,其中包含1个类型为TextInputTableViewCell的动态原型单元格。
 在原型单元格的内容视图中,我添加了一个textField。

  1. 如何使用userInfo中的数据填充文本字段?
  2. 用户编辑后,如何获取每个textField的数据?
  3. 我已经读过SO我应该使用标签,但是其他人说这种方法容易出现bug和脆弱的。无论如何,我不知道如何使用标签或其他方法从字段中获取数据。请指教。

    import Foundation
    import UIKit
    import Firebase
    
     class TextInputTableViewCell: UITableViewCell, UITextFieldDelegate{ 
          @IBOutlet weak var textField: UITextField!
    
         //closure when the text changes
         var textChangedCallBack: ((_ cell: TextInputTableViewCell, _ text:String) -> ())?
          //Delegate method called when the text field loses focus
         func textFieldDidEndEditing(_ textField: UITextField) {
        textChangedCallBack?(self,textField.text!)
      }
    }//end of class TextInputTableViewCell
    
    
    
    class EditProfile: UIViewController, UITableViewDelegate,UITableViewDataSource,UITextFieldDelegate {
    
     var dbRef:FIRDatabaseReference! //create a reference to Firebase
     var userInfo = [FireBaseData]() //this array will hold all data under userType in Firebase
    
    
    
    @IBOutlet weak var tableView: UITableView!
    @IBAction func saveToFirebase(_ sender: Any) {  
    
     //will post data from text fields  to firebase
    }
    
    
    struct Item {
        var name:String
        var editable:Bool
    }
    
    let placeHolderItems = [
        Item(name: "Name", editable: false),
        Item(name: "Phone Number", editable: true),
        Item(name: "Email", editable: true),
        Item(name: "Flat Number", editable: true),
        Item(name: "Street Address", editable: true),
        Item(name: "Postcode", editable: true)
    ]
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
       self.dbRef = FIRDatabase.database().reference().child("Cleaners")
        self.tableView.delegate = self
        self.tableView.dataSource = self
    }
    
       override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(true)
    
       //get user's profile from firebase
        self.startObservingDB { (userProfile) in
    
            if userProfile.count > 0 {
                self.userInfo = userProfile
                 self.tableView.reloadData()
            }
        }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return placeHolderItems.count
    }
    
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "TextInputCell") as! TextInputTableViewCell
    
        cell.textField.isEnabled = placeHolderItems[indexPath.row].editable
        cell.textField.placeholder = placeHolderItems[indexPath.row].name
    
     //After viewWillAppear finishes, self.userInfo will have the profile of
     //the user. How can I get here each textField  of the tableView so I can
       //populate each one of them with data from  self.userInfo?
    
    
    
             if !self.userInfo.isEmpty{
    
    switch indexPath.row{
        case 0:
             cell.textField.text = self.userInfo[0].FirstName + " " + self.userInfo[indexPath.row].LastName
        case 1:
            cell.textField.text = self.userInfo[0].PhoneNumber
    
        case 2: cell.textField.text = self.userInfo[0].EmailAddress
    
        case 3: cell.textField.text = self.userInfo[0].FlatNumber
    
        case 4: cell.textField.text = self.userInfo[0].StreetAddress
    
        case 5: cell.textField.text = self.userInfo[0].PostCode
    
        default:
            break
         }
     }
    
    
        cell.textChangedCallBack = {(cell, text) in
    
            //get the cell's current index path 
            if let path = tableView.indexPath(for: cell) {
    
                //get the item at that row
                var item = self.placeHolderItems[path.row]
    
                //update the item with the new name  
            }  
        }
    
        return cell
      }
     }//end of EditProfileclass
    
    
    
    
    
    extension EditProfile {
    
    
      //get user's profile in order to populate it in tableView
       func startObservingDB(callback:@escaping ((_ snapShot: [FireBaseData]) -> Void)) {
    
        //check if user is singed in
        guard let uid = FIRAuth.auth()?.currentUser?.uid  else {
            return
        }  
    
        dbRef.child(uid).child("profile").observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in
            var profileData = [FireBaseData]()
    
            for keyVal in snapshot.children{
    
                let userData = FireBaseData(snapshot: keyVal as! FIRDataSnapshot)
                profileData.append(userData)
                           }
            callback(profileData)
    
        }, withCancel: { (Error:Any) in 
            print("error is \(Error as! String)")
    
        })
        dbRef.removeAllObservers()
    
    }//end of startObserving
    
    }//end of EditProfile Class
    


    enter image description here

    enter image description here

2 个答案:

答案 0 :(得分:1)

通常要解决的问题是:用户在表格视图单元格中编辑了一个文本字段,现在我们要相应地更新数据模型。但哪个单元格包含此文本字段?

“哪个”这个概念实际上意味着:包含单元格所代表的索引路径是什么?如果我们知道这一点,我们可以轻松更新模型,因为如果我们的表视图数据源设计正确,我们就已经知道如何通过索引路径访问模型。

所以我所做的只是将视图层次结构从文本字段向上移动到单元格,然后询问表格视图此单元格表示的索引路径。这是我的应用中常用的模式:

GatewayFilter

答案 1 :(得分:1)

你可以试试这个。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "TextInputCell") as! TextInputTableViewCell

    cell.textField.isEnabled = placeHolderItems[indexPath.row].editable
    cell.textField.placeholder = placeHolderItems[indexPath.row].name


    if !self.userInfo.isEmpty{

        switch indexPath.row {
        case 0:
            cell.textField.text = self.userInfo[0].FirstName + " " + self.userInfo[indexPath.row].LastName
        case 1:
            cell.textField.text = self.userInfo[0].PhoneNumber

        case 2: cell.textField.text = self.userInfo[0].EmailAddress

        case 3: cell.textField.text = self.userInfo[0].FlatNumber

        case 4: cell.textField.text = self.userInfo[0].StreetAddress

        case 5: cell.textField.text = self.userInfo[0].PostCode

        default:
            break
        }
    }

    // Add tag to cell textField as cell current index
    cell.textField.tag = indexPath.row
    //Observer changes as user edits
    cell.txtField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)

    return cell
}

//MARK: - TextField Delegate
func textFieldDidChange(textfield: UITextField) {
    print("TextField \(String(describing: textfield.text)) Tag : \(textfield.tag)")

    switch textfield.tag {
    case 0:
        let Name  = textfield.text // or store where ever you want in sepearte array or update in userInfo
    case 1:
        let PhoneNumber   = textfield.text

    case 2:
        let EmailAddress   = textfield.text

    case 3:
        let FlatNumber   = textfield.text

    case 4:
        let StreetAddress   = textfield.text

    case 5:
        let PostCode  = textfield.text
    default:
        break
    }

}

// Don't forget to add UITextFieldDelegate