在UITableView的自定义原型单元中,UITextField值替换为其他原型单元 [英] In custom Prototype Cell in UITableView, UITextField value replaces with other Prototype Cell

查看:50
本文介绍了在UITableView的自定义原型单元中,UITextField值替换为其他原型单元的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我拿了一个UITableView,在里面我用了2个prototype单元,现在在那些原型单元中,我已经取了1个UITextField.

I have taken one UITableView and inside that I have used 2 prototype cells, now in those prototype cells, i have taken 1 UITextField.

现在,当我运行应用程序并在第一个原型单元格中输入值时,我滚动UITableView,然后第一个原型单元格的文本字段值将变为最后一个原型单元格的文本字段值.因此,每次我向下滚动或向上滚动时,它都会替换.有时它变成空白.

Now when I run the app and enter value in first prototype cell then i scroll UITableView, then first prototype cell's textfield value come to last prototype cell's textfield value. so it replace everytime i scrolldown or scroll up. sometime it goes blank.

这是我的代码

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

}

推荐答案

TL; DR(只需给我代码)

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

The Github link: https://github.com/starkindustries/CustomTableView

问题

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

As others have pointed out, dequeueReusableCellWithIdentifier will reuse the same cell references when scrolling. Take a look at the gif below for a visual demonstration of this problem.

gif表格中的表有20行(屏幕上无法容纳的行数更多).每行都有一个文本字段.我分别在第一行到第四行中键入一",二",三",四".

The table in the gif has 20 rows (more rows than can fit on screen). Each row has a single textfield. I typed in "one", "two", "three", "four" into rows one through four respectively.

如您所见,当我向下滚动时,两个",三个"和一个"神奇地出现在底部(不必要的行为).这是因为当滚动到屏幕之外时,这些单元格从顶部出队,并在底部再次被重用.

As you can see, when I scroll down, "two", "three", and "one" magically appear at the bottom (unwanted behavior). This is because those cells dequeued from the top when scrolled off screen and got reused again on the bottom.

讨论

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

After much research on the web and stack overflow, I suggest you store the values of the textfields in an array when they change. Then you can set the textfield text accordingly in the cellForRowAt method. @Rob perfectly explains how to solve this using the model-view-controller pattern in his answer here: https://stackoverflow.com/a/38272077/2179970. I've implemented his suggestion into this following example.

工作原理

  1. 首先,您将设置协议,以便自定义UITableViewCell(视图)可以发送 消息返回给ViewController,以通知其文本字段 改变了. ViewController将实现该协议.该单元格将调用协议方法.
  2. 您的应用程序用户将输入文本.这将触发 textFieldDidChange(_:)在自定义UITableViewCell类中.
  3. textFieldDidChange(_:)将调用TableViewController的 委托方法cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField)通知控制器其文本 改变了.
  4. 控制器将更新其文本数组(模型)以保存 改变.
  5. cellForRowAt将更新单元格的文本字段的 内容是否需要重复使用.
  1. First, you'll setup a protocol so that the custom UITableViewCell (the view) can send a message back to the ViewController to notify it that its textfield changed. ViewController will implement the protocol. The cell will call the protocol method.
  2. The user of your app will type in text. This will trigger textFieldDidChange(_:) within the custom UITableViewCell class.
  3. The textFieldDidChange(_:) will call the TableViewController's delegate method cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField) to notify the controller that it's text changed.
  4. The controller will update its text array (the model) to save the change.
  5. The cellForRowAt will update the cell's textfield's contents appropriately if it needs to be reused.

解决方案

协议:

// Protocol from Step 1
protocol CustomCellDelegate: class {
    // This is the function that the ViewController will implement
    func cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField)
}

自定义UITableViewCell:

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

}

View Controller:

View Controller:

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

结果

我像以前一样在前四行中键入相同的一个",两个",三个",四个".这次,表格的行为符合预期:文本字段内容出现在我放置它们的位置,并且它们不会随机消失/出现.

I typed in the same "one", "two", "three", "four" into the first four rows as before. This time, the table behaves as expected: the textfield contents appear where I put them and they don't disappear/appear randomly.

Github链接

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

参考

从笔尖初始化自定义UITableViewCell而不使用dequeueReusableCellWithIdentifier

UITableView中的UITextField,输入的值重新出现在其他单元格中

UITableViewCell中的UITextField和模态视图中的验证

这篇关于在UITableView的自定义原型单元中,UITextField值替换为其他原型单元的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆