Как обратиться к контроллеру с класса uitableviewcell в Swift
У меня есть следующее
- ViewController
- Tableview
- CustomCell
Я использовал NIB (файл .xib) для ячейки, которая использует класс CustomCell. Этот пользовательский класс ячейки обрабатывает IBAction для некоторого касания кнопки соты. Я хотел бы ссылаться на ViewController и некоторые его переменные внутри него. Как я должен это делать (доступ к ViewController)?
Спасибо!
Ответы
Ответ 1
Я бы не стал создавать такую зависимость между ячейкой и контроллером представления - это делает архитектуру более сложной и ячейку нельзя использовать повторно.
Я предлагаю вам использовать шаблон делегирования, который может показаться немного сложным - хотя вы уже используете (UITableViewDelegate
- типичный пример):
- создайте протокол
MyCellProtocol
с одним методом didTapCell
, принимая UITableViewCell
и/или некоторые пользовательские данные, которые вы хотите передать в контроллер представления - создать открытое свойство делегата в вашей пользовательской ячейке:
weak var cellDelegate: MyCellProtocol?
- в обработчике
didTapXXX
или didSelectRowAtIndexPath
вашей ячейки вызовите self.cellDelegate?.didTapCell()
, передав ожидаемые параметры - в вашем контроллере представления, реализовать
MyCellProtocol
- в
cellForRowAtIndexPath
вашего контроллера представления, при создании/снятии очереди с ячейки установите cellDelegate
свойства cellDelegate
значение self
В этот момент, когда в вашей ячейке выполняется didTapCell
, didTapCell
метод didTapCell
контроллера представления, и оттуда вы можете делать все, что вам нужно для достижения.
Ключевым моментом является то, что вместо того, чтобы заставить ячейку обрабатывать нажатие/выделение ячейки, уведомите контроллер представления и дайте ему выполнить свою работу.
Ответ 2
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
}
}
Внутри твоей клетки
if let myViewController = parentViewController as? MyViewController {
print(myViewController.title)
}
Ответ 3
Я не думаю, что вы должны это сделать, и, вероятно, вы делаете что-то неправильно, но если вам действительно нужно это, то просто получите свойство в своем классе CustomCell
.
var viewController : UIViewController
то при создании ячейки в cellForRowAtIndexPath
установите свойство
cell.viewController = self
после этого вы можете легко получить доступ к контроллеру представления из кода ячейки:
self.viewController.doSomething()
Но опять же, на мой взгляд, вы должны перепроектировать свой код. Ячейка не должна заботиться о контроллере. Он должен заботиться только о том, чтобы показывать себя и ничего больше
Ответ 4
Лучший способ - реализовать делегирование. Ваш делегат сообщит контроллеру просмотра о нажатии кнопки. И, в свою очередь, ваш контроллер просмотра (который соответствует протоколу для вышеуказанного делегата) будет обрабатывать задачу, которую вы хотите выполнить при событии клика. (Учебники по шаблонам делегаций доступны в Интернете, вы можете пройти через них, если хотите знать, как делать делегирование).
Ответ 5
добавить расширение
extension UITableViewCell {
var viewControllerForTableView : UIViewController?{
return ((self.superview as? UITableView)?.delegate as? UIViewController)
}
}
теперь downCast как ниже
if let viewController = self.viewControllerForTableView as? AnyController{
print(viewController.variable)
}
,
Ответ 6
Прочитайте другие комментарии о том, что вы действительно хотите использовать альтернативный подход, прежде чем пытаться это сделать, но с помощью этого расширения вы сможете перейти к dataSource
и delegate
, оба из которых должны быть 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
}
}
}