Ссылка с UITableViewCell на родительский UITableView?

Есть ли способ получить доступ к собственному UITableView из UITableViewCell ?

Храните weak ссылку на таблицуView в ячейке, которую вы установили в -tableView:cellForRowAtIndexPath: из вашего -tableView:cellForRowAtIndexPath: данных вашей таблицы.

Это лучше, чем полагаться на self.superview чтобы всегда быть точным. TableView является хрупким. Кто знает, как Apple может перестроить иерархию представлений UITableView в будущем.

Вот более удобный способ сделать это, что не зависит от какой-либо конкретной иерархии UITableView. Он будет работать с любой будущей версией iOS, если UITableView не изменит имя classа вообще. Мало того, что это крайне маловероятно, но если это произойдет, вам все равно придется ретушировать ваш код.

Просто импортируйте категорию ниже и получите свою ссылку с помощью [myCell parentTableView]

 @implementation UIView (FindUITableView) -(UITableView *) parentTableView { // iterate up the view hierarchy to find the table containing this cell/view UIView *aView = self.superview; while(aView != nil) { if([aView isKindOfClass:[UITableView class]]) { return (UITableView *)aView; } aView = aView.superview; } return nil; // this view is not within a tableView } @end 

 // To use it, just import the category and invoke it like so: UITableView *myTable = [myTableCell parentTableView]; // It can also be used from any subview within a cell, from example // if you have a UILabel within your cell, you can also do: UITableView *myTable = [myCellLabel parentTableView]; // NOTE: // If you invoke this on a cell that is not part of a UITableView yet // (ie, on a cell that you just created with [[MyCell alloc] init]), // then you will obviously get nil in return. You need to invoke this on cells/subviews // that are already part of a UITableView. 

ОБНОВИТЬ
Существует некоторая дискуссия в комментариях о том, является ли сохранение слабых ссылок лучшим подходом. Это зависит от ваших обстоятельств. Прохождение иерархии представлений имеет небольшое ограничение времени исполнения, поскольку вы зацикливаетесь до тех пор, пока не будет идентифицирован целевой UIView. Насколько глубоки ваши взгляды? С другой стороны, сохранение ссылки на каждую ячейку имеет минимальное ограничение памяти (слабая ссылка – это указатель в конце концов), и, как правило, добавление отношений объектов там, где они не нужны, считается плохой практикой проектирования OO по многим причинам, и (см. подробности в комментариях ниже).

Что еще более важно, сохранение ссылок на таблицы внутри ячеек добавляет сложность кода и может привести к ошибкам, поскольку UITableViewCells можно использовать повторно. Не случайно UIKit не включает свойство cell.parentTable . Если вы определите свой собственный, вы должны добавить код для его управления, и если вы не сделаете это эффективно, вы можете ввести утечки памяти (т. Е. Клетки живут за время жизни их таблицы).

Поскольку обычно вы используете категорию выше, когда пользователь взаимодействует с ячейкой (выполняется для одной ячейки), а не при раскладке таблицы в [tableView:cellForRowAtIndexPath:] (выполняется для всех видимых ячеек), время выполнения стоимость должна быть незначительной.

Xcode 7 beta, Swift 2.0

Это отлично работает для меня, по-моему, это не имеет ничего общего с иерархией или чем-то еще. До сих пор у меня не было проблем с этим подходом. Я использовал это для многих асинхронных обратных вызовов (например, когда запрос API был выполнен).

Класс TableViewCell

 class ItemCell: UITableViewCell { var updateCallback : ((updateList: Bool)-> Void)? //add this extra var @IBAction func btnDelete_Click(sender: AnyObject) { let localStorage = LocalStorage() if let description = lblItemDescription.text { //I delete it here, but could be done at other class as well. localStorage.DeleteItem(description) } updateCallback?(updateList : true) } } 

Внутри classа представления таблицы, который реализует DataSource и Delegate

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell: ItemCell = self.ItemTableView.dequeueReusableCellWithIdentifier("ItemCell") as! ItemCell! cell.updateCallback = UpdateCallback //add this extra line cell.lblItemDescription?.text = self.SomeList[indexPath.row].Description return cell } func UpdateCallback(updateTable : Bool) //add this extra method { licensePlatesList = localStorage.LoadNotificationPlates() LicenseTableView.reloadData() } 

Конечно, вы можете поместить любую переменную в updateCallback и соответствующим образом изменить ее в tableView .

Кто-то, возможно, захочет сказать мне, если это будет полезно использовать, просто, чтобы быть уверенным.

Вы должны добавить ссылку обратно в UITableView при создании ячейки представления таблицы.

Однако почти наверняка, что вы действительно хотите, это ссылка на ваш UITableViewController …, который требует того же, установите его как делегат ячейки, когда вы создадите ячейку и передаете ее в представление таблицы.

Альтернативный подход, если вы подключаете действия, состоит в том, чтобы построить ячейки в IB, с controllerом представления таблиц в качестве владельца файлов – затем подключить кнопки в ячейке к действиям в controllerе табличного представления. Когда вы загружаете ячейку xib с помощью loadNibNamed, пройдите в controllerе представления, когда владелец и действия кнопки будут подключены обратно к controllerу табличного представления.

Если у вас есть пользовательские classы для вашего UITableViewCells, вы можете добавить переменную типа id в заголовок своей ячейки и синтезировать переменную. После того, как вы установите переменную при загрузке ячейки, вы можете делать то, что вам нравится, с помощью таблицы или любого другого более высокого вида без особых хлопот или накладных расходов.

cell.h

  // interface id root; // propery @property (nonatomic, retain) id root; 

cell.m

@synthesize root;

tableviewcontroller.m

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // blah blah, traditional cell declaration // but before return cell; cell.root = tableView; } 

Теперь вы можете вызвать любой из методов tableview из вашей ячейки, используя корневую переменную. (например, [root reloadData]);

Ах, возвращает меня в старые добрые времена программирования вспышки.

Два метода в других ответах: (A) хранить ссылку на таблицу или (B) подходить к надзору.

Я всегда использовал бы что-то вроде (A) для объектов модели и (B) для ячеек таблицы.

ячейки

Если вы имеете дело с UITableViewCell, то AFAIK вы должны либо иметь UITableView под рукой (например, вы находитесь в методе делегата таблицы), либо иметь дело с видимой ячейкой, которая находится в иерархии представлений. В противном случае вы, возможно, будете делать что-то неправильно (обратите внимание, что «может быть хорошо»).

Ячейки повторно используются повторно, и если у вас есть тот, который не отображается, единственная реальная причина, по которой существует эта ячейка, связана с оптимизацией производительности iOS UITableView (более медленная версия iOS была бы выпущена и, надеюсь, деактивизировала бы ячейку, когда она вышла из экрана ) или потому, что у вас есть конкретная ссылка на него. Думаю, это, вероятно, причина того, что ячеек таблицы не снабжен методом экземпляра tableView.

Итак, (B) дает правильный результат для всех iOS до сих пор и всех будущих, пока они радикально не изменили работу просмотров.

Хотя для того, чтобы избежать написания обобщаемого кода снова и снова, я бы использовал следующее:

 +(id)enclosingViewOfView:(UIView*)view withClass:(Class)returnKindOfClass { while (view&&![view isKindOfClass:returnKindOfClass]) view=view.superview; return(view); } 

и метод удобства:

 +(UITableView*)tableForCell:(UITableViewCell*)cell { return([self enclosingViewOfView:cell.superview withClass:UITableView.class]); } 

(или категории, если хотите)

BTW, если вас беспокоит влияние цикла с 20 или около того итераций такого размера на производительность вашего приложения, не делайте этого.

модели

Если вы говорите об объекте модели, который отображается в ячейке, то определенно эта модель может / должна знать о своей родительской модели, которая может использоваться для поиска или инициирования изменений в таблице (таблицах), которую может использовать модель ячейки (например, A), но менее хрупким с будущими обновлениями iOS (например, в один прекрасный день они могут сделать кеш повторного использования UITableViewCell для каждого повторного использования, а не для каждого повторного использования в представлении таблицы, в тот день все реализации, которые используют слабые ссылочный метод сломается).

Метод модели TH будет использоваться для изменения данных, отображаемых в ячейке (например, изменений модели), поскольку изменения будут распространяться везде, где отображается модель (например, какой-либо другой UIViewController где-то еще в приложении, протоколирование, …)

Метод cell будет использоваться для действий tableview, что, вероятно, всегда будет плохой идеей, если ячейка даже не является подзором таблицы (хотя это ваш код, идите в гайки).

В любом случае используйте единичный тест, а не предполагая, что, по-видимому, более чистый код работает только при обновлении iOS.

 UITableView *tv = (UITableView *) self.superview.superview; UITableViewController *vc = (UITableViewController *) tv.dataSource; 
  • Создайте эскиз или изображение AVPlayer в текущее время
  • Лучший подход для синтаксического анализа XML на iPhone
  • Каков наилучший способ перетащить NSMutableArray?
  • глубокая изменчивая копия NSMutableDictionary
  • Управление несколькими асинхронными соединениями NSURLConnection
  • Правильный способ выхода из приложения iPhone?
  • Есть ли iPhone SDK API для твиттера?
  • MKAnnotation, простой пример
  • Как я могу изменить NSArray в Objective-C?
  • Как использовать CaptiveNetwork для получения текущего имени точки доступа Wi-Fi
  • Как запустить UITableView на последней ячейке?
  • Давайте будем гением компьютера.