UITableViewCell 中的 UITextView 在 `textViewDidBeginEditing` 方法中首次分配失败

Posted

技术标签:

【中文标题】UITableViewCell 中的 UITextView 在 `textViewDidBeginEditing` 方法中首次分配失败【英文标题】:UITextView in UITableViewCell fail to be assigned its delegate for the first time in `textViewDidBeginEditing` method 【发布时间】:2019-06-12 16:13:03 【问题描述】:

原帖:

如标题所示。我确保当单元格在cellForRowAt 方法中启动时,单元格的文本视图将被分配来自该方法的委托。事实上,单元格中还有另一个文本字段,它适用于文本字段,文本字段委托方法按预期调用。但是,当涉及到textview时,我做了同样的事情,但是在单元格初始化之后,委托似乎变成了nil,并且没有按预期调用textview委托方法。

我尝试过使用 Playground:设置一个包含 textview 的视图控制器,为其分配一个委托,并向 textViewDidBeginEditing 方法添加一条打印消息,当我点击 textview 时,该消息按预期打印出来.我真的不确定是什么导致了这个问题。

我唯一确定的是,在cellForRowAt tableview 数据源方法中,委托仍然存在。我不知道之后会发生什么。有什么想法吗?

仅供参考:category 是文本字段,detail 是文本视图。

对于cellForRowAt 方法

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

    //the rest of the added cells for other categories
    let cellForOtherCategories = tableView.dequeueReusableCell(withIdentifier: addListTableViewCellID, for: indexPath) as! AddListTableViewCell
    cellForOtherCategories.addListTableViewCellDelegate = self

    cellForOtherCategories.category.delegate = self

    print("Before delegate is set")

    cellForOtherCategories.detail.delegate = self

    print("After delegate is set.")

    print(cellForOtherCategories.detail.delegate.debugDescription)


    return cellForOtherCategories

对于文本视图委托:

func textViewDidBeginEditing(_ textView: UITextView) 
    print("This should go first")


更新 1:

文本视图的委托方法只有在第二次点击文本视图时才会被调用。但这仍然很奇怪,为什么在文本视图被点击时没有调用委托方法第一次以后。

为了说明这种情况,假设有一个文本视图,分配了一个委托,实现了包含打印消息的textViewDidBeginEditing。当我第一次点击文本视图时,消息没有打印出来。但是,在我将文本视图作为第一响应者(在其他地方点击)并再次点击文本视图后,委托方法被调用。

更新 2:

由于textViewShouldBeginEditingtextViewDidBeginEditing 之前被调用,我尝试将打印消息放在textViewShouldBeginEditing 中以测试此委托方法是否有效。结果证明是有效的。那么现在问题进一步深入,为什么第一次没有调用textViewDidBeginEditing,而调用了另一个方法?

更新 3:

在我将单元格的代表分配为它自己并相应地调整我的程序后,同样的问题再次出现。由于操场上的测试有效,我认为问题实际上不在于委托的分配。其他原因导致了问题。当我考虑我的程序和测试代码之间是否有任何区别时,它是观察者。 (或者可能是别的什么?但我不知道,因为其他主要是各种视图,这对调用 textview 委托方法应该没有任何影响。)

我有一个观察者,它的通知是UIResponder.keyboardWillHideNotification,所以观察者的方法将并且应该只在我点击 textview 并随后调用 textview 委托方法后调用。

当涉及到观察者时,UITextView 是否有任何幕后发生,例如第一次点击时不会调用 textview 委托方法 textViewDidBeginEditing?由于textfield没有问题。

【问题讨论】:

能否请您发布单元格的初始化代码,您分配代表的位置等等。还有 cellForRow 和未被调用的方法。 @jastrada 嗨,我添加了方法。 你是说print(cellForOtherCategories.detail.delegate.debugDescription) 打印nil @rmaddy 不,我要说的是print(cellForOtherCategories.detail.delegate.debugDescription) 打印带有值的可选值。这表明委托已分配。但是当我继续尝试print("This should go first") 时,它失败了,即没有打印任何内容。 你把textViewDidBeginEditing函数放在哪里了?确保它不在另一个函数中。它需要位于视图控制器类或扩展的顶层。 【参考方案1】:

这很麻烦,因为拥有 tableView 的 ViewController 将成为多个 textView 和 textField 的委托。我建议在 AddListTableViewCell 中创建一个设置函数。

在那里您将设置代表,应该是每个单元格。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cellForOtherCategories = tableView.dequeueReusableCell(withIdentifier: addListTableViewCellID, for: indexPath) as! AddListTableViewCell

    cellForOtherCategories.setupCell()

    return cellForOtherCategories

然后,在 AddListTableViewCell 上,您将拥有该方法:

func setupCell() 
    self.categoryTextField.delegate = self

    self.categoryTextView.delegate = self

    //And whatever you need..

最后将扩展名添加到单元格以便能够分配它。

extension AddListTableViewCell: UITextViewDelegate 

    func textViewDidBeginEditing(_ textView: UITextView) 
        print("There you go")
    


【讨论】:

我尝试使用单元格本身作为它的委托,它工作得很好,但我想要将委托“集中”为视图控制器,以便我可以处理所有文本视图和文本字段在一个视图控制器中委托方法。这就是为什么我试图将文本视图的委托分配为视图控制器本身。如果这个集中的想法真的行不通,并且无法将 textview 委托分配给视图控制器,我想我会改回单元格本身。 就设计和简洁代码而言,这不是一个好的做法,而且我怀疑存在一些问题,因为它是同一类型的多个单元格的代表。相反,当您将其分配为 tableView 的委托时,它只是一个。 我想要这样做的另一个原因是这些视图的委托方法实际上调用了几乎相同的函数,而且我发现让每个子视图都实现委托方法相当重复。因此,我只想通过将它们全部收集在视图控制器中来编写它们一次。这适用于文本字段,实际上我有两个文本字段的委托分配给视图控制器,它们都工作正常。但是到了textview的时候,就无法成功分配delegate了……好奇怪……

以上是关于UITableViewCell 中的 UITextView 在 `textViewDidBeginEditing` 方法中首次分配失败的主要内容,如果未能解决你的问题,请参考以下文章

根据内容大小属性设置 UIText 视图的宽度

从 UIText 字段的用户输入更改 UIView 框架的高度和宽度

无法更改 UIText 视图的字体(使用 Web 服务时)

如何从 UITextfields UIMenuController 中删除不需要的 UIMenuItems?

UITableViewCell 中的 UIDatePicker 更新 UITableViewCell 文本标签

更改 UITableViewCell 中的对象也更改了重用 UITableViewCell 的对象