У меня есть 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
}
}