I have the following:
I used a .xib file for the cell, which
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
}
}
Inside your cell
if let myViewController = parentViewController as? MyViewController {
print(myViewController.title)
}
Best way is to implement Delegation. Your delegate will inform the view controller about the button click. And, In turn your view controller (who is conforming the protocol for above delegate) will handle the task that you want to perform on click event. (Delegation pattern tutorials are available online. you can go through them if you want to know how to do delegation).
Read the other comments about really wanting to use an alternate approach before trying this, but using this extension will allow you to get to the dataSource
and delegate
both of which should be the UITableViewController
extension UITableViewCell {
var tableView:UITableView? {
get {
for var view = self.superview ; view != nil ; view = view!.superview {
if view! is UITableView {
return (view! as UITableView)
}
}
return nil
}
}
var tableViewDataSource:UITableViewDataSource? {
get {
return self.tableView?.dataSource
}
}
var tableViewDelegate:UITableViewDelegate? {
get {
return self.tableView?.delegate
}
}
}
I wouldn't create this kind of dependency between the cell and the view controller - that makes the architecture more intricate and the cell not reusable.
I suggest you to use the delegation pattern, which may sound a little complicated - although you're already using (UITableViewDelegate
is a typical example):
MyCellProtocol
with one method didTapCell
, accepting a UITableViewCell
and/or some custom data you want to pass to the view controllerweak var cellDelegate: MyCellProtocol?
didTapXXX
handler or didSelectRowAtIndexPath
of your cell, call self.cellDelegate?.didTapCell()
, passing the expected parametersMyCellProtocol
cellForRowAtIndexPath
of your view controller, when creating/dequeuing the cell, set its cellDelegate
property to self
At this point, when a tap is done in your cell, the didTapCell
method of the view controller is called, and from there you can do whatever you need to achieve.
The key point is: rather than making the cell handle the cell tap/selection, notify the view controller and let it do the job.
add Extension
extension UITableViewCell {
var viewControllerForTableView : UIViewController?{
return ((self.superview as? UITableView)?.delegate as? UIViewController)
}
}
now downCast as below
if let viewController = self.viewControllerForTableView as? AnyController{
print(viewController.variable)
}
.
I don't think you should do that and probably you're doing something wrong but if you really-really need it then just have a property in your CustomCell
class.
weak var viewController : UIViewController
then when you create the cell in cellForRowAtIndexPath
set the property
cell.viewController = self
after that you can easily access the view controller from within the cell code:
self.viewController.doSomething()
But again, in my opinion, you should redesign your code. The cell should not care about the controller. It should care only about displaying itself and nothing else