【问题标题】:Adding another cell to tableview when done editing textview inside cell完成在单元格内编辑 textview 后向 tableview 添加另一个单元格
【发布时间】:2019-01-08 23:04:16
【问题描述】:

我只想以我不使用故事板的事实作为开头。

我有一个包含多个部分的 tableview,其中填充了我以编程方式创建的 tableViewcells。这些自定义单元格包括一个带有一些占位符文本的文本字段。我希望用户能够做的是点击文本字段,输入他们的条目,然后点击“Enter”以关闭键盘,然后在他们刚刚编辑的单元格下方创建一个新单元格。这与提醒应用中发生的行为非常相似。

我很难弄清楚如何访问 tableview 的数据模型(一个数组)并弄清楚该单元格位于哪个部分,将新字符串添加到数组中,然后添加另一个哑单元格有占位符文本。

【问题讨论】:

    标签: ios swift uitableview


    【解决方案1】:

    首先,您必须创建一种在单元格和视图控制器之间进行通信的方式。 您可以为此使用委托模式或回调。 例如:

    final class TextFieldCell: UITableViewCell {
    
        // MARK: - IBOutlets
        @IBOutlet weak var textField: UITextField!
    
        // MARK: - Local variables
        var callback: ((_ text: String) -> Void)?
    
        // MARK: - Lyfecycle
        override func awakeFromNib() {
            super.awakeFromNib()
            textField.delegate = self
        }
    }
    

    别忘了调用我们的回调:

    extension TextFieldCell: UITextFieldDelegate {
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            textField.resignFirstResponder()
            callback?(textField.text!)
            return true
        }
    }
    

    太棒了!现在我们将字符串从单元发送到控制器!

    您的视图控制器的代码示例(简化版):

    class ViewController: UIViewController {
        // MARK: - IBOutlets
        @IBOutlet weak var tableView: UITableView!
    
        // MARK: - Local variables
        var titles = ["Hello", "world"]
    }
    
    // MARK: - UITableViewDataSource
    
    extension ViewController: UITableViewDataSource {
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return titles.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let textFieldCell = tableView.dequeueReusableCell(withIdentifier: "textFieldCell", for: indexPath) as! TextFieldCell
    
            textFieldCell.textField.placeholder = titles[indexPath.row]
            textFieldCell.callback = { [weak self] newTitle in // don't forget about memory leaks
                guard let `self` = self else { return }
    
                // calculating index path for new row
                let newIndexPath = IndexPath(row: indexPath.row + 1, section: indexPath.section)
    
                // appending a new row in table view
                self.titles.append(newTitle)
                self.tableView.insertRows(at: [newIndexPath], with: UITableView.RowAnimation.automatic)
            }
    
            return textFieldCell
        }
    }
    

    【讨论】:

    • 我注意到的几件事:对于回调参数类型,只使用类型,而不是参数名称((String) -> Void)?。接下来,`self`可能是self,编译器知道你在本地范围内声明它。最后,动画类型是UITableView.RowAnimation,你可以用UITableView.RowAnimation.automatic代替.automatic
    • 是的,我知道,但这一切都是为了让经验不足的开发人员更好地理解。
    • 感谢您的帮助!我实施了您的解决方案,并且运行良好;我只是对它为什么起作用有一些疑问。 1)为什么回调变量的格式很奇怪?我的猜测是它是一个闭包。 2)我不确定为什么在 cellforRowAt 委托方法而不是 didSelectRowAt 方法中调用回调。 3) 为什么使用self
    • 很高兴听到! 1) 是的,回调它只是一个闭包。你可以发送任何数据抛出这个。 2)当您点击您的单元格时,将调用 didSelectRowAt。您在 cellForRow 方法中为 textField 回调设置了一个闭包,因此在那里调用它。 3) 如果你在任何闭包中使用类变量,ypu 必须写 [weak self] 以避免内存泄漏。您可以阅读有关内存管理和强引用的信息来理解这一点。祝你学习顺利!
    猜你喜欢
    • 2018-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-22
    • 2019-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多