在UITableView中的自定义原型单元格中,UITextField值将replace为其他原型单元格
我采取了一个UITableView
和里面,我已经使用了2个prototype
单元格,现在在这些原型单元格中,我已经采取了1个UITextField
。
现在,当我运行应用程序,并在第一个原型单元格中input值,然后滚动UITableView
,然后第一个原型单元格的文本字段值来最后原型单元格的文本字段值。 所以它每次我滚动或滚动。 有时它变成空白。
这是我的代码
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if(indexPath.row==0) { Client_MobileCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier_MobileCell forIndexPath:indexPath]; cell.lblTitle.text = [arrTitle objectAtIndex:indexPath.row]; cell.txtMobile.placeholder = [arrPlaceholder objectAtIndex:indexPath.row]; // cell.txtMobile.tag = indexPath.row+100; return cell; } else { // Client_Common_Cell *cell = (Client_Common_Cell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier_CommonCell forIndexPath:indexPath]; Client_Common_Cell *cell = (Client_Common_Cell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier_CommonCell]; // cell.txtCommon.tag = indexPath.row+100; cell.delegate = self; if(indexPath.row == 1 || indexPath.row == 2 || indexPath.row == 3 || indexPath.row == 4){ if(indexPath.row == 2) cell.txtCommon.secureTextEntry = YES; else if(indexPath.row == 4){ cell.txtCommon.keyboardType = UIKeyboardTypeEmailAddress; } cell.imgArrow.hidden = YES; cell.btnSelection.hidden = YES; } else{ cell.btnSelection.hidden = NO; cell.imgArrow.hidden = NO; } cell.lblTitle.text = [arrTitle objectAtIndex:indexPath.row]; cell.txtCommon.placeholder = [arrPlaceholder objectAtIndex:indexPath.row]; return cell; }
}
当您使用dequeueReusableCellWithIdentifier
,您的单元格将被重用。 这意味着当用户滚动tableview
,移出屏幕的cell
将被重新使用以显示将要移动到屏幕上的cell
的内容。
尽pipe这有助于节省内存,但它造成的问题是,在加载新cell
的内容之前, cell
需要准备好显示。
在你的情况下,你似乎需要维护用户input到cell
的textfield
中的值。
所以要解决你的问题,如果在tableview
中没有那么多的cells
,只需停止重用cell
(对每个单元实例使用alloc-init / new)。 从你的代码看起来你只有不到10个单元,这将是解决问题的最快方法。
否则,如果有大量的单元格,每当用户在cell
的textfield
中input值时,将其保存在一个array
。 并从数组中获取值并将其设置到cellForRowAtIndexPath
方法中的textfield
中。
TL; DR(给我的代码)
Github链接: https : //github.com/starkindustries/CustomTableView
问题
正如其他人指出的, dequeueReusableCellWithIdentifier
将在滚动时重用相同的单元格引用。 看看下面的gif,以便对这个问题进行直观的演示。
gif中的表格有20行(多行可以放在屏幕上)。 每行都有一个文本字段。 我把“一”,“二”,“三”,“四”分别放入第一到第四行。
正如你所看到的,当我向下滚动时,“两”,“三”和“一”神奇地出现在底部(不需要的行为)。 这是因为这些单元格在滚动屏幕时从顶端出队,并在底部再次被重用。
讨论
经过对Web和堆栈溢出的大量研究后,我build议您将文本字段的值存储在数组中。 然后,您可以在cellForRowAt
方法中相应地设置文本字段文本。 @Rob完美地解释了如何在他的答案中使用模型 – 视图 – 控制器模式来解决这个问题: https ://stackoverflow.com/a/38272077/2179970。 我已经将这个build议应用到了这个例子中。
怎么运行的
- 首先,您将设置一个协议,以便自定义的UITableViewCell( 视图 )可以将消息发送回ViewController,以通知其文本字段已更改。 ViewController将执行该协议。 单元格将调用协议方法。
- 您的应用的用户将input文字。 这将触发自定义UITableViewCell类中的
textFieldDidChange(_:)
。 -
textFieldDidChange(_:)
将调用TableViewController的委托方法cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField)
来通知控制器文本已更改。 - 控制器将更新其文本数组( 模型 )以保存更改。
-
cellForRowAt
将更新单元格的文本字段的内容,如果需要重新使用。
解决scheme
协议:
// Protocol from Step 1 protocol CustomCellDelegate: class { // This is the function that the ViewController will implement func cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField) }
自定义UITableViewCell:
class MyTableViewCell: UITableViewCell, UITextFieldDelegate { // Protocol reference (Step 1) weak var delegate: CustomCellDelegate? @IBOutlet weak var textField: UITextField! override func awakeFromNib() { super.awakeFromNib() // Initialization code // (Step 2) Add a "textFieldDidChange" notification method to the text field control. textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: UIControlEvents.editingChanged) } // Step 2 func textFieldDidChange(_ textField: UITextField) { delegate?.cell(cell: self, updatedCustomTextField: textField) } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } }
视图控制器:
class MyTableViewController: UITableViewController, CustomCellDelegate { var myTexts: [String?]! override func viewDidLoad() { super.viewDidLoad() myTexts = Array(repeating: nil, count: 20) let nib = UINib(nibName: "MyTableViewCell", bundle: nil) self.tableView.register(nib, forCellReuseIdentifier: "MyTableViewCell") } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 20 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { print("CellForRowAt: " + indexPath.row.description) let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as! MyTableViewCell // Step 5: TableView updates cell contents if reused cell.delegate = self cell.textField.text = myTexts[indexPath.row] return cell } // MARK: - CustomCellDelegate Method // Step 3: The cell will call this protocol method to message the controller func cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField) { // when the cell tells us that its text field's value changed, update our own model if let indexPath = tableView.indexPath(for: cell), let string = textField.text { // Step 4: The controller updates the model: print("delegate method cell updatedCustomTextField") myTexts[indexPath.row] = string } } }
结果
与前面一样,我在前四行中input了相同的“一”,“二”,“三”,“四” 这一次,表格的行为如预期的那样:文本字段的内容出现在我放置它们的地方,并且不会随机消失/出现。
Github链接
这里是项目的链接: https : //github.com/starkindustries/CustomTableView
参考
从nib初始化自定义的UITableViewCell,不带dequeueReusableCellWithIdentifier
UITableView中的UITextFields,input值重新出现在其他单元格中
UITableViewCell中的UITextField和模态视图中的validation
- 我的SearchDisplayController不能很好地处理UIViewController中的UITableView
- UIPageControl和UIPageviewController不同步
- SonarQube“托管在您的服务器上” + Travis CI + Swift
- 从WSDL为iPhone生成SOAP类
- 块完成后,如何访问__blockvariables?
- 使用GPUImageFilter时发生崩溃
- MKMapSnapshotOptions:添加自定义引脚注解视图或UIView的快照
- 具有自动布局和节重装的UITableViewHeaderFooterView子类不能很好地协同工作
- 快速登录/注销导航过程