在UITableView中的自定义Prototype Cell中,UITextField值替换为其他Prototype Cell

时间:2016-06-06 07:49:24

标签: ios objective-c xcode uitableview uitextfield

我已经使用了一个UITableView并在里面使用了2 prototype个单元格,现在在这些原型单元格中,我已经使用了1 UITextField

现在,当我运行应用程序并在第一个原型单元格中输入值时,我滚动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;
}

}

2 个答案:

答案 0 :(得分:2)

TL; DR(只需给我代码)

Github链接:https://github.com/starkindustries/CustomTableView

问题

正如其他人所指出的那样,dequeueReusableCellWithIdentifier会在滚动时重复使用相同的单元格引用。看看下面的gif,可以直观地看到这个问题。

gif中的表有20行(比屏幕上可以容纳的行数多)。每行都有一个文本字段。我分别在“一”,“二”,“三”,“四”中输入一到四行。

正如你所看到的,当我向下滚动时,“两个”,“三个”和“一个”神奇地出现在底部(不需要的行为)。这是因为当从屏幕滚动并在底部再次重复使用时,这些单元格从顶部出列。

enter image description here

<强>讨论

经过对网络和堆栈溢出的大量研究后,我建议您在更改时将文本字段的值存储在数组中。然后,您可以在cellForRowAt方法中相应地设置文本字段文本。 @Rob完美地解释了如何使用模型 - 视图 - 控制器模式在他的答案中解决这个问题:https://stackoverflow.com/a/38272077/2179970。我已经在下面的例子中实现了他的建议。

如何运作

  1. 首先,您将设置协议,以便自定义UITableViewCell(视图)可以发送 回到ViewController的消息,通知它它的文本字段 改变。 ViewController将实现该协议。该单元将调用协议方法。
  2. 您应用的用户将输入文字。这将触发 自定义UITableViewCell类中的textFieldDidChange(_:)
  3. textFieldDidChange(_:)将调用TableViewController 委托方法cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField)通知控制器它的文本 改变。
  4. 控制器将更新其文本数组(模型)以保存 更改。
  5. cellForRowAt将更新单元格的文本字段 如果需要重复使用,请适当填写。
  6. 解决方案

    协议:

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

    结果

    我像往前一样在前四行输入相同的“一”,“二”,“三”,“四”。这一次,表格表现如预期:文本字段内容出现在我放置的位置,它们不会消失/随机出现。

    enter image description here

    Github Link

    以下是该项目的链接:https://github.com/starkindustries/CustomTableView

    <强>参考

    Init custom UITableViewCell from nib without dequeueReusableCellWithIdentifier

    UITextFields in UITableView, entered values reappearing in other cells

    UITextField in UITableViewCell and validation in modal view

答案 1 :(得分:1)

使用dequeueReusableCellWithIdentifier时,您的单元格将被重复使用。这意味着当用户滚动tableview时,移出屏幕的cell将被重复使用以显示即将移动到屏幕上的cell的内容。

尽管这有助于节省内存,但它导致的问题是cell在加载新cell的内容之前需要准备好显示。

在您的情况下,您似乎需要维护用户在textfield的{​​{1}}中输入的值。

因此,为了解决您的问题,如果cell中没有那么多cells,只需停止重用tableview(对每个单元格实例使用alloc-init / new)。从您的代码看,您的单元格少于10个,这将是解决问题的最快方法。

否则,如果有大量单元格,则只要用户在cell的{​​{1}}中输入值,就将其保存在textfield中。并从数组中获取值,并将其设置为cell方法中的array