У меня есть UITableViewCell, связанный с объектом, и мне нужно определить, видима ли ячейка. Из проведенного мной исследования это означает, что мне нужно каким-то образом получить доступ к UITableView, который содержит его (оттуда есть несколько способов проверить, видимо ли это). Поэтому мне интересно, имеет ли UITableViewCell указатель на UITableView, или если есть какой-либо другой способ получить указатель из ячейки?
Как получить UITableView из UITableViewCell?
Ответ 1
Чтобы избежать проверки версии iOS
id view = [tableViewCellInstance superview];
while (view && [view isKindOfClass:[UITableView class]] == NO) {
    view = [view superview]; 
}
    UITableView *tableView = (UITableView *)view;
		Ответ 2
В iOS7 beta 5 UITableViewWrapperView - это просмотр UITableViewCell.  Также UITableView - это просмотр UITableViewWrapperView.
Итак, для iOS 7 решение
 
UITableView *tableView = (UITableView *)cell.superview.superview;
Итак, для iOSes до iOS 6 решение
 
UITableView *tableView = (UITableView *)cell.superview;
Ответ 3
Прежде чем iOS7, супервизор ячейки был UITableView, который содержал его. Начиная с iOS7 GM (предположительно, в публичном релизе) супервизор ячейки - это UITableViewWrapperView, а его супервизор - UITableView. Существует два решения проблемы.
 Решение №1: Создайте категорию UITableViewCell
@implementation UITableViewCell (RelatedTable)
- (UITableView *)relatedTable
{
    if ([self.superview isKindOfClass:[UITableView class]])
        return (UITableView *)self.superview;
    else if ([self.superview.superview isKindOfClass:[UITableView class]])
        return (UITableView *)self.superview.superview;
    else
    {
        NSAssert(NO, @"UITableView shall always be found.");
        return nil;
    }
}
@end
Это хорошая замена для замены cell.superview, упрощает реорганизацию существующего кода - просто выполните поиск и замените с помощью [cell relatedTable], а затем введите assert, чтобы убедиться, что если иерархия представления изменилась или в будущем он будет появляться сразу же в ваших тестах.
 Решение №2: добавьте слабую ссылку UITableView на UITableViewCell
@interface SOUITableViewCell
   @property (weak, nonatomic) UITableView *tableView;
@end
Это гораздо лучший дизайн, хотя для существующих проектов потребуется немного больше рефакторинга кода. В вашем tableView:cellForRowAtIndexPath используйте SOUITableViewCell в качестве класса ячеек или убедитесь, что ваш собственный класс ячеек подклассифицирован из SOUITableViewCell и присваивает tableView свойству cellView таблицы. Внутри ячейки вы можете обратиться к содержащему таблицу с помощью self.tableView.
Ответ 4
Расширение Swift 3
Рекурсивный
extension UIView {
    func parentView<T: UIView>(of type: T.Type) -> T? {
        guard let view = self.superview else {
            return nil
        } 
        return (view as? T) ?? view.parentView(of: T.self)
    }
}
extension UITableViewCell {
    var tableView: UITableView? {
        return self.parentView(of: UITableView.self)
    }
}
Использование цикла
extension UITableViewCell {
    var tableView: UITableView? {
        var view = self.superview
        while (view != nil && view!.isKind(of: UITableView.self) == false) {
            view = view!.superview
        }
        return view as? UITableView
    }
}
		Ответ 5
Если он виден, он имеет супервизор. И... сюрприз... супервизор - это объект UITableView.
Однако наличие супервизора не является гарантией того, что вы находитесь на экране. Но UITableView предоставляет методы для определения того, какие ячейки видны.
И нет, нет специальной ссылки из ячейки в таблицу. Но когда вы подклассифицируете UITableViewCell, вы можете ввести его и установить его при создании. (Я сделал это сам, прежде чем я подумал о иерархии subview.)
Обновление для iOS7: Apple изменила иерархию subview здесь. Как обычно, при работе с вещами, которые не описаны подробно, всегда есть риск, что все изменится. Очень удобно "обходить" иерархию представлений до тех пор, пока объект UITableView не будет найден.
Ответ 6
Я создал категорию в UITableViewCell, чтобы получить родительский tableView:
@implementation UITableViewCell (ParentTableView)
- (UITableView *)parentTableView {
    UITableView *tableView = nil;
    UIView *view = self;
    while(view != nil) {
        if([view isKindOfClass:[UITableView class]]) {
            tableView = (UITableView *)view;
            break;
        }
        view = [view superview];
    }
    return tableView;
}
@end
Бест,
Ответ 7
Все, что вы в конечном итоге можете сделать, вызывая супер-просмотр или через цепочку ответчиков, будет очень хрупким. Лучший способ сделать это, если ячейки хотят что-то знать, - передать объект в ячейку, которая отвечает на какой-либо метод, который отвечает на вопрос, который хочет задать ячейка, и чтобы контроллер реализовал логику определения того, что ответить (из вашего вопроса, я думаю, ячейка хочет знать, что-то видимо или нет).
Ответ 8
Swift 2.2.
Расширение для UIView, которое рекурсивно ищет представление определенного типа.
import UIKit
extension UIView {
    func lookForSuperviewOfType<T: UIView>(type: T.Type) -> T? {
        guard let view = self.superview as? T else {
            return self.superview?.lookForSuperviewOfType(type)
        }
        return view
    }
}
или более компактный (благодаря kabiroberai):
import UIKit
extension UIView {
    func lookForSuperviewOfType<T: UIView>(type: T.Type) -> T? {
        return superview as? T ?? superview?.superviewOfType(type)
    }
}
В вашей ячейке вы просто назовете это:
let tableView = self.lookForSuperviewOfType(UITableView)
// Here we go
Помните, что UITableViewCell добавляется в UITableView только после выполнения cellForRowAtIndexPath.
Ответ 9
Вот версия  Swift, основанная на приведенных выше ответах. Я обобщен в ExtendedCell для последующего использования.
import Foundation
import UIKit
class ExtendedCell: UITableViewCell {
    weak var _tableView: UITableView!
    func rowIndex() -> Int {
        if _tableView == nil {
            _tableView = tableView()
        }
        return _tableView.indexPathForSelectedRow!.row
    }
    func tableView() -> UITableView! {
        if _tableView != nil {
            return _tableView
        }
        var view = self.superview
        while view != nil && !(view?.isKindOfClass(UITableView))! {
            view = view?.superview
        }
        self._tableView = view as! UITableView
        return _tableView
    }
}
Надеюсь, что эта помощь:)
Ответ 10
Я основал это решение по предложению Гейба, что объект UITableViewWrapperView - это супервизор объекта UITableViewCell в iOS7 beta5.
Подкласс UITableViewCell:
- (UITableView *)superTableView
{
    return (UITableView *)[self findTableView:self];
}
- (UIView *)findTableView:(UIView *)view
{
    if (view.superview && [view.superview isKindOfClass:[UITableView class]]) {
        return view.superview;
    }
    return [self findTableView:view.superview];
}
		Ответ 11
Я заимствовал и немного изменил этот ответ и придумал следующий фрагмент.
- (id)recursivelyFindSuperViewWithClass:(Class)clazz fromView:(id)containedView {
    id containingView = [containedView superview];
    while (containingView && ![containingView isKindOfClass:[clazz class]]) {
        containingView = [containingView superview];
    }
    return containingView;
}
Прохождение в классе предлагает гибкость для перемещения и получения других точек зрения, кроме UITableView, в некоторых случаях.
Ответ 12
Мое решение этой проблемы несколько похоже на другие решения, но использует элегантный для цикла и является коротким. Он также должен быть надежным в будущем:
- (UITableView *)tableView
{
    UIView *view;
    for (view = self.superview; ![view isKindOfClass:UITableView.class]; view = view.superview);
    return (UITableView *)view;
}
		Ответ 13
UITableView *tv = (UITableView *) self.superview.superview;
BuyListController *vc = (BuyListController *) tv.dataSource;
		Ответ 14
Вместо супервизора попробуйте использовать [ "UItableViewvariable" visibleCells].
Я использовал это в петлях foreach для прокрутки ячеек, которые видел приложение, и это сработало.
for (UITableView *v in [orderItemTableView visibleCells])//visibleCell is the fix.
{
  @try{
    [orderItemTableView reloadData];
    if ([v isKindOfClass:[UIView class]]) {
        ReviewOrderTableViewCell *cell = (ReviewOrderTableViewCell *)v;
        if (([[cell deleteRecord] intValue] == 1) || ([[[cell editQuantityText] text] intValue] == 0))
            //code here 
    }
  }
}
Работает как шарм.
Ответ 15
Минимально проверенный, но этот не общий пример Swift 3 работает:
extension UITableViewCell {
    func tableView() -> UITableView? {
        var currentView: UIView = self
        while let superView = currentView.superview {
            if superView is UITableView {
                return (superView as! UITableView)
            }
            currentView = superView
        }
        return nil
    }
}
		Ответ 16
этот код `UITableView *tblView=[cell superview]; предоставит вам экземпляр UItableview, который содержит ячейку просмотра табуляции
Ответ 17
Я предлагаю вам пройти иерархию представлений таким образом, чтобы найти родительский UITableView:
- (UITableView *) findParentTableView:(UITableViewCell *) cell
{
    UIView *view = cell;
    while ( view && ![view isKindOfClass:[UITableView class]] )
    {
#ifdef DEBUG
        NSLog( @"%@", [[view  class ] description] );
#endif
        view = [view superview];
    }
    return ( (UITableView *) view );
}
В противном случае ваш код сломается, когда Apple снова изменит иерархию представления.
Другой ответ, который также пересекает иерархию, является рекурсивным.
Ответ 18
UITableViewCell Internal View Hierarchy Change in iOS 7
Using iOS 6.1 SDK
    <UITableViewCell>
       | <UITableViewCellContentView>
       |    | <UILabel>
Using iOS 7 SDK
    <UITableViewCell>
       | <UITableViewCellScrollView>
       |    | <UIButton>
       |    |    | <UIImageView>
       |    | <UITableViewCellContentView>
       |    |    | <UILabel>
The new private UITableViewCellScrollView class is a subclass of UIScrollView and is what allows this interaction:
![enter image description here][1]
  [1]: http://i.stack.imgur.com/C2uJa.gif
http://www.curiousfind.com/blog/646 Благодарю вас.
Ответ 19
Вы можете получить его с помощью одной строки кода.
UITableView *tableView = (UITableView *)[[cell superview] superview];
		Ответ 20
extension UIView {
    func parentTableView() -> UITableView? {
        var viewOrNil: UIView? = self
        while let view = viewOrNil {
            if let tableView = view as? UITableView {
                return tableView
            }
            viewOrNil = view.superview
        }
        return nil
    }
}