UIView 扩展获取 UITableViewCell?

Posted

技术标签:

【中文标题】UIView 扩展获取 UITableViewCell?【英文标题】:UIView extension to get UITableViewCell? 【发布时间】:2017-02-18 06:00:14 【问题描述】:

如果 UIView 的特定实例确实是 UITableViewCell 的子视图,我正在制作一个 UIView 扩展,它返回一个可能的 UITableViewCell。

这个想法是稍后我可以将 UITableViewCell 引用传递给 UITableView 的 indexPath(for:) 方法来获取单元格的索引路径。

因此,如果我的表格视图单元格包含 UITextField,我能够在调用 UITextFieldDelegate 的 textFieldDidEndEditing(_ textField: UITextField) 方法时识别该文本字段来自哪个单元格。

到目前为止,这是我想出的:

extension UIView 
    var tableViewCell: UITableViewCell? 
        get 
            var view = self
            while let superview = view.superview 
                if let tableViewCell = superview as? UITableViewCell 
                    return tableViewCell
                
                view = superview
            
            return nil
        
    

我有两个问题:

    由于我是使用 Swift 编程的新手,请问是否有更好的(Swiftier?)方法来编写这个?

    这是识别包含正在编辑的 UITextField 的 UITableViewCell 的索引路径的好方法吗?有没有更好的办法?

我实际上是 Swift 和 Stack Overflow 的新手,如果我做错了什么,非常抱歉(请多多原谅),我希望得到您的指导。谢谢。

【问题讨论】:

【参考方案1】:

最简洁的方法是简单地标记您的单元格文本字段。

例如,您也可以使用indexPath.row 进行标记。

然后在UITextFieldDelegate 方法textFieldDidBeginEditing(_:) 中只需检查begins editing 的textField 的标签,您就可以简单地从中创建一个NSIndexPath。

但是,如果您在不同的部分中有多个部分和 UITextField,则需要部分和行才能使 NSIndexPath 正确。

根据您在 tableView 中有多少 textFields,解决方案可能是创建一个 NSDictionary 来保留对部分和行的引用。

【讨论】:

【参考方案2】:

这是一种计算 indexPath 的有趣方法,但更安全的方法可能是使用 textView 的委托方法并计算 tableViewCell 相对于 tableView 的 indexPath。

class TableViewCell: UITableViewCell 
    @IBOutlet weak var textField: UITextField!


class ViewController: UIViewController 
    var indexPath: IndexPath?
    @IBOutlet weak var tableView: UITableView!

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableViewCell else  return UITableViewCell() 
        cell.textField.delegate = self
        return cell
    


extension ViewController: UITextFieldDelegate 
    func textFieldDidBeginEditing(_ textField: UITextField) 
         let point = textField.convert(.zero, to: tableView)
         indexPath = tableView.indexPathForRow(at: point)
    

【讨论】:

更正您的答案。 1: 这是一个 UITextField 2: 他不能在 viewDidLoad 中设置委托,因为它包含在一个单元格中。 3: 需要在 cellForRowAtIndexPath: 方法中设置委托。 4 UIViewController 中不需要插座和属性,因为它包含在一个单元格中。 5:如果要设置delegate = self,则需要将UITextFieldDelegate添加到类中。【参考方案3】:

这些是替代方案: 1.根据点找到单元格。

func textFieldDidEndEditing(_ sender: UITextField) 
        let tableViewTouchPoint:CGPoint = sender.convert(CGPointZero, to:self.tableView)
        let indexPath = self.tableView.indexPathForRow(at: tableViewTouchPoint)

    

为相同的Tableview创建一个扩展

extension UITableView 

  func indexPathForView(_ view: UIView) -> IndexPath? 
    let tableViewTouchPoint:CGPoint = view.convert(CGPointZero, to:self)
        let indexPath = self.indexPathForRow(at: tableViewTouchPoint)
    return indexPath
  

使用它

   let indexPath = self.tableView.indexPathForView(textField) 

    基于子视图标签。在 CellForRowATIndex 中,将标签设置为等于 indexPath.row。然后,要取回 IndexPath 使用:

    让 index = sender.tag

    让 indePath = IndexPath(row: index, section: 0)

【讨论】:

这 2 个选项都是当前已回答的两个答案中的一个选项。 好吧,格式化答案对我来说和你们发布的时候都需要时间。运气不好! 不用担心,因为提供了多种选择而被赞成:) 只是想提一下标签方法在“使用 beginUpdates 和 endUpdates 插入单元格”世界(核心数据 + 获取的结果控制器等)中不起作用(由于未在旧单元格上调用 CellForRowAtIndex 导致错误) )。点法仍然有效。 是的,但是对于一般的简单tableview渲染,标签是最好和最简单的解决方案,是大多数人的首选。

以上是关于UIView 扩展获取 UITableViewCell?的主要内容,如果未能解决你的问题,请参考以下文章

UIView 的扩展

如何将 circleView 进度添加到 UIView 扩展到所有 UIView?

使用自动布局为 UIView 应用渐变背景

苹果手表应用冲突uiview扩展

使用径向渐变作为 UIView 的扩展

在 Swift 中平滑扩展 UIView 动画