jjzjj

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

coder 2024-01-11 原文

我使用了一个 UITableView 并在其中使用了 2 个 prototype 单元格,现在在那些原型(prototype)单元格中,我使用了 1 个 UITextField .

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

这是我的代码

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

问题

正如其他人所指出的,dequeueReusableCellWithIdentifier 将在滚动时重复使用相同的单元格引用。请查看下面的 gif 动图,以直观地演示此问题。

gif 中的表格有 20 行(多于屏幕显示的行数)。每行都有一个文本字段。我分别在第一到第四行输入了“一”、“二”、“三”、“四”。

如您所见,当我向下滚动时,“二”、“三”和“一”神奇地出现在底部(不需要的行为)。这是因为当滚动到屏幕外时,这些单元格从顶部出队,并在底部再次使用。

讨论

在对网络和堆栈溢出进行大量研究后,我建议您在文本字段发生变化时将其值存储在数组中。然后您可以在 cellForRowAt 方法中相应地设置文本字段文本。 @Rob 在他的回答中完美地解释了如何使用模型- View - Controller 模式解决这个问题:https://stackoverflow.com/a/38272077/2179970 .我已将他的建议实现到以下示例中。

工作原理

  1. 首先,您将设置一个协议(protocol),以便自定义 UITableViewCell( View )可以发送一个 消息返回给 ViewController 以通知它它的文本字段 变了。 ViewController 将实现该协议(protocol)。单元将调用协议(protocol)方法。
  2. 您的应用程序的用户将输入文本。这将触发 textFieldDidChange(_:) 在自定义 UITableViewCell 类中。
  3. textFieldDidChange(_:) 将调用 TableViewController 的 委托(delegate)方法 cell(cell: UITableViewCell, updatedCustomTextField textField: UITextField) 通知 Controller 它是文本 变了。
  4. Controller 将更新其文本数组(模型)以保存 改变。
  5. cellForRowAt 将更新单元格的文本字段 如果需要重复使用,则内容适当。

解决方案

协议(protocol):

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

}

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

结果

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

Github 链接

这是项目的链接: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

关于ios - 在 UITableView 的自定义 Prototype Cell 中,UITextField 值替换为其他 Prototype Cell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37652121/

有关ios - 在 UITableView 的自定义 Prototype Cell 中,UITextField 值替换为其他 Prototype Cell的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  4. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  5. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  6. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  7. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  8. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  9. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  10. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

随机推荐