在UIViewController中,我有一个UITableView,其中包含1个类型为TextInputTableViewCell
的动态原型单元格。
在原型单元格的内容视图中,我添加了一个textField。
我已经读过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
答案 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