2017-06-12 59 views
14

我在Swift 3中使用Xcode 8.2.1。我有一个包含UITextView的自定义UITableViewCell。当我输入textView时,自定义单元格自动增长。这部分工作正常。我还想在输入特定单元格时使用相同的数据更新其他单元格。例如:如何同时更新每个自定义tableview单元格数据?

当我键入文本第五单元,自动在第11,第15和第18单元格中输入相同的数据。那些细胞也必须自动生长。我已经将数据添加到数组的特定索引。但它并没有反映在tableView。我如何实现这一功能?

请通过以下代码,我已经实施到目前为止。这updateCellHeight方法是一个自定义的委托方法。当用户键入textView时会调用此方法。

func updateCellHeight(indexPath: IndexPath, comment: String) { 

    let currentCellLyricVal = self.traduzioneArray[indexPath.row]["rics"] 
    tempIndexArray.removeAll() 

    for (index,element) in traduzioneArray.enumerated() { 

     let lyricVal = element["rics"] 
     if currentCellLyricVal == lyricVal { 
      tempIndexArray.append(index) 
     } 
    } 
    for index in tempIndexArray { 
     self.traduzioneArray[index]["ione"] = comment 
     self.lyricsTableView.beginUpdates() 
     self.lyricsTableView.endUpdates() 
    } 
} 

func textViewDidChange(_ textView: UITextView) { 
    self.delegate.updateCellHeight(indexPath: self.cellIndexPath, comment: textView.text) 
} 

回答

7

我想用数据自动进入问题是,在resignFirstResponder()通话重装的细胞的结果的事实。

这似乎是对数据重新加载你居然放弃一些细胞,并通过cellForRowAt:要求换新表视图很符合逻辑。旧的可能不一样,所以他们resignFirstResponder()

更新单元格文本的一种方法是直接更改单元格内容。您可以为文本查看内容执行此操作。不幸的是,如果没有触发heightForRowAt:,则无法直接更改单元格高度。

UPDATE2:有针对iOS 8+上表视图结合直接细胞操纵和AutomaticDimension的溶液。
完美工作的UITextView。检查下面的更新。这是最后的结果看起来的样子:

enter image description here

UPDATE1:代码示例直接细胞操纵加入

使用简单的模型来保存表格视图数据:

// Simple model, for the example only 
class Model { 
    // The value of the text field 
    var value: String? 
    // The type of the cell 
    var type: CustomCell.CellType = .typeA 

    init(value: String) { 
     self.value = value 
    } 

    init(value: String, type: CustomCell.CellType) { 
     self.value = value 
     self.type = type 
    } 
} 

// Init the model. 
var tableData = [ 
    Model(value: "Cell Type A", type: .typeA), 
    Model(value: "Cell Type B", type: .typeB), 
    Model(value: "Cell Type B", type: .typeB), 
    Model(value: "Cell Type A", type: .typeA), 
    Model(value: "Cell Type B", type: .typeB)] 

而且这样的代表:

// Delegate to update visible cells in the table view when text field value change. 
protocol TextChangeDelegate { 
    func textChangedAtCell(_ cell: CustomCell, text: String?) 
} 

然后初始化您的自定义单元格:

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

    // Will crash if identifier is not registered in IB 
    let cell = tableView.dequeueReusableCell(withIdentifier: "customCell") as! CustomCell 

    // For this to work you need to update the model on each text field text change 
    cell.textValue.text = tableData[indexPath.row].value 
    cell.index = indexPath.row 
    cell.type = tableData[indexPath.row].type 
    cell.textChangeDelegate = self 

    return cell 
} 

在自定义单元格:

class CustomCell: UITableViewCell { 

    // The type of the cell. Cells with same type will be updated simultaneously. 
    enum CellType { 
     case typeA 
     case typeB 
    } 

    // Very simple prototype cell with only one text field in it 
    @IBOutlet weak var textValue: UITextField! 

    // Default type 
    var type = CellType.typeA 
    // Index in the model. Not optional (or other special assumptions on initial value) 
    // for simplicity of the example. 
    var index = 0 
    var textChangeDelegate: TextChangeDelegate? 
} 

extension CustomCell: UITextFieldDelegate { 

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { 

     // Assume we will return true. Any logic could appear here. 
     // If we need to return false, don't call the delegate method. 
     let result = true 

     if result { 
      let nsString = textField.text as NSString? 
      let newString = nsString?.replacingCharacters(in: range, with: string) 
      print("New: \(newString ?? "(nil)")") 

      textChangeDelegate?.textChangedAtCell(self, text: newString) 
     } 

     return result 
    } 
} 

这是如何实现的直接小区接入,即视图控制器的TextChangeDelegate无需重新加载数据:

extension ViewController: TextChangeDelegate { 

    func textChangedAtCell(_ cell: CustomCell, text: String?) { 

     // Only visual update. Skip the cell we are currently editing. 
     for visibleCell in tableView.visibleCells where visibleCell != cell { 
      if let currentCell = visibleCell as? CustomCell, 
       tableData[currentCell.index].type == cell.type { 
        currentCell.textValue.text = text 
      } 
     } 

     // Update the model (including invisible cells too) 
     for (index, data) in tableData.enumerated() where data.type == cell.type { 
      tableData[index].value = text 
     } 

     // Avoid reloading here, as this will trigger resignFirstResponder and you will 
     // have issues when jumping from text field to text field across cells. 
    } 
} 

您现在可以在具有相同CellType的所有单元格上同时进行文本更新。这个例子使用UITextField(为UITextView检查UPDATE2)。

UPDATE2在这里。带有UITextView的单元,同时具有文本和高度调整功能。

使用前面示例中的模型和控制器(稍微更改,因为您将使用新单元格)。 利用UITableViewCell并将UITextView放入其中。在自动版式设置约束文本视图:

Add constraints for auto resize

记住禁用滚动和反弹到文本视图(否则你不会有自动高度)。 不要忘记将textView的委托链接到UITextViewCell子类。

在细胞

然后,使用

func textViewDidChange(_ textView: UITextView) { 
    self.textChangeDelegate?.textChangedAtCell(self, text: textView.text) 
} 

然后,超级重要,在视图控制器的viewDidLoad,加上这两个设置

tableView.estimatedRowHeight = 50 
tableView.rowHeight = UITableViewAutomaticDimension 

并注册细胞:

tableView.register(UINib(nibName: "CustomTextViewCell", bundle: nil), 
        forCellReuseIdentifier: "customTextViewCell") 

最后,将此代码添加到TextChangeDelegate从UPDATE1执行实际高度更新技巧:

func textChangedAtCell(_ cell: UITableViewCell, text: String?) { 

    <code from UPDATE 1 goes here> 

    tableView.beginUpdates() 
    tableView.endUpdates() 
} 

享受!每次你需要更新电池使用此代码时

+0

能否请您用代码 – IKKA

+0

解释更新:提供了如何使用直接单元操作的代码示例。 – kr45ko

+0

更新为iOS 8+的全面解决方案。现在,您可以同时进行自动文本更新和单元高度更新,而不会松动键盘。 – kr45ko

2

首先,从故事板或在您的tableView Cell类设置textviews NumberOfLines = 0

在高度为行委托具有

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
    return UITableViewAutomaticDimension 
} 

在您的viewDidLoad中添加这些行:

tableView.rowHeight = UITableViewAutomaticDimension 
tableView.estimatedRowHeight = 140 

在tableViewController

func updateCellHeight(indexPath: IndexPath, comment: String) { 

    let currentCellLyricVal = self.traduzioneArray[indexPath.row]["rics"] 
    tempIndexArray.removeAll() 

    for (index,element) in traduzioneArray.enumerated() { 

     let lyricVal = element["rics"] 
     if currentCellLyricVal == lyricVal { 
      tempIndexArray.append(index) 
     } 
    } 
    for index in tempIndexArray { 
     self.traduzioneArray[index]["ione"] = comment 
    } 
     tableView.reloadRows(at: [IndexPath(row: 11, section: 1),IndexPath(row: 13, section: 1)], with: UITableViewRowAnimation.none) 
} 

通过具有被设置为0的线条和自动尺寸高度单元格会自动调整大小。此外,请确认您在cellForRow方法定制细胞委托设置为self。

+0

,但我不能手动提到重载特定行像13,11,15,etc.One更多的是“reloadRows”导致自动关闭键盘。 – IKKA

3

一旦用新数据更新数据集。用更新的数据集重新加载特定的单元格。

func updateCellHeight(indexPath: IndexPath, comment: String) { 
     DispatchQueue.main.async { 
      let currentCellLyricVal = self.traduzioneArray[indexPath.row]["rics"] 
      tempIndexArray.removeAll() 

      for (index,element) in traduzioneArray.enumerated() { 

       let lyricVal = element["rics"] 
       //You have to skip the current cell. by checking index != indexPath.row 
       if currentCellLyricVal == lyricVal, index != indexPath.row { 
        tempIndexArray.append(index) 
       } 
      } 

      for index in tempIndexArray { 
       self.traduzioneArray[index]["ione"] = comment 

       let updatedIndexPath = IndexPath(row: index, section: indexPath.section) 
        if let visibleCellIndexPaths = tableView.indexPathsForVisibleRows { 
         if visibleCellIndexPaths.contains(updatedIndexPath) { 
          tableView.reloadRows(at: [updatedIndexPath], with: .automatic) 
         } 
        } 
      } 
     } 
    } 

注:如果修改后的数据集内小区是可见的那么只有我们必须重新加载特定的细胞。

+0

但是,使用此代码键盘会在每次输入每个字母时自动关闭。 – IKKA

+0

为每个字符更改重新加载单元格并不是很好的做法。一旦完成编辑,我们可以更新单元格。 – Subramanian

+0

@JAK FUNC textViewDidEndEditing(_的TextView:UITextView的){ self.delegate.updateCellHeight(indexPath:self.cellIndexPath,评论:textView.text) } – Subramanian

1

func updateCellHeight(indexPath: IndexPath, comment: String) { 

    //update dataModel according to new text 
    ... 
    //then reload visible tableview rows 
    //pay atttention to beginUpdates endUpdates methods. 
    //This do the trick) 

    tableView.beginUpdates() 
    tableView.reloadRows(at: indexPathsForVisibleRows ?? [], with: .none) 
    tableView.endUpdates() 

} 
相关问题