如何从Swift中的uitableviewcell类引用控制器

Nor*_*ias 36 cocoa-touch uitableview uikit ios swift

我有以下内容

  1. 视图控制器
  2. 的tableView
  3. CustomCell

我使用NIB(.xib文件)作为单元格,它使用CustomCell类.此自定义单元格类处理IBAction以触摸单元格的按钮.我想引用ViewController及其中的一些变量.我该怎么做(访问ViewController)?

谢谢!

Ant*_*nio 53

我不会在单元格和视图控制器之间创建这种依赖关系 - 这会使架构更复杂,并且单元格不可重用.

我建议你使用委托模式,这可能听起来有点复杂 - 虽然你已经在使用(UITableViewDelegate是一个典型的例子):

  • MyCellProtocol使用一种方法创建协议didTapCell,接受UITableViewCell要传递给视图控制器的一个和/或一些自定义数据
  • 在自定义单元格中创建公共委托属性: weak var cellDelegate: MyCellProtocol?
  • didTapXXX处理程序或didSelectRowAtIndexPath您的单元格中,调用self.cellDelegate?.didTapCell(),传递预期的参数
  • 在你的视图控制器中,实现 MyCellProtocol
  • cellForRowAtIndexPath视图控制器中,在创建/出列单元格时,将其cellDelegate属性设置为self

此时,当您在单元格中完成点击时,将didTapCell调用视图控制器的方法,然后您可以执行任何操作.

关键点在于:不是让单元格处理单元格点击/选择,而是通知视图控制器并让它完成工作.

  • 这可能有效。但是,当将dataSource封装到不同的类时,应该这样做(不要将DS放入控制器中),您需要找到一种不同的方式来连接单元格和控制器。您可以做的一件事是使用tableView委托方法willDisplayCell将tableview分配为单元格的委托。然后,您需要在prepareForReuse中取消它们的链接,并根据所使用的语言进行dealloc或deinit。如果有多个活动的控制器监听相同的通知,则通知也不是理想的解决方案。 (2认同)

Bla*_*ank 21

extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}
Run Code Online (Sandbox Code Playgroud)

你的牢房里面

if let myViewController = parentViewController as? MyViewController {
    print(myViewController.title)
}
Run Code Online (Sandbox Code Playgroud)

  • 在Swift 4中,`.nextResponder()`被改为`.next` (4认同)
  • 我想从嵌套在 uitableviewcell 内的 uicollectionviewcell 执行 segue,这非常有效!谢谢。 (2认同)

And*_*kha 14

我不认为你应该这样做,可能你做错了但如果你真的需要它,那么你的CustomCell班级就有了一个属性.

weak var viewController : UIViewController
Run Code Online (Sandbox Code Playgroud)

然后在cellForRowAtIndexPath设置属性时创建单元格

cell.viewController = self
Run Code Online (Sandbox Code Playgroud)

之后,您可以从单元格代码中轻松访问视图控制器:

self.viewController.doSomething()
Run Code Online (Sandbox Code Playgroud)

但是,在我看来,你应该重新设计你的代码.单元格不应该关心控制器.它应该只关心自己展示而不是其他

  • 它当然不是.一个不好的做法就是让代码在按钮的动作中处理很多模型的东西.在这种情况下,一个好的做法是在按钮的动作中只有一行代码.该行应发布通知或调用委托方法.然后控制器应对此调用或此通知做出反应并运行所有需要的代码.控制器,而不是细胞.我希望你明白我在说什么 (3认同)
  • 在大多数UI框架中,访问对象的容器非常常见,例如在ActionScript中你可以使用this.parent调用父级,而根据我在Apple语言中的经验,Apple似乎没有足够的可视化编程语言经验,所以我猜这个解决方案是非常可以接受和聪明的,我会给它+1 (2认同)

Gop*_*han 5

add Extension

 extension UITableViewCell {

        var viewControllerForTableView : UIViewController?{
            return ((self.superview as? UITableView)?.delegate as? UIViewController)
        }

    }
Run Code Online (Sandbox Code Playgroud)

now downCast as below

   if let viewController = self.viewControllerForTableView as? AnyController{

       print(viewController.variable)

   } 
Run Code Online (Sandbox Code Playgroud)

.