如何从UITableViewCell获取UITableView?

sin*_*inθ 97 iphone xcode objective-c tableview ios

我有一个UITableViewCell链接到一个对象,我需要告诉我单元格是否可见.从我已经完成的研究中,这意味着我需要以某种方式访问UITableView包含它的内容(从那里,有几种方法可以检查它是否可见).所以我想知道是否UITableViewCell有一个指针UITableView,或者是否还有其他方法从单元格获取指针?

Muh*_*ris 151

避免iOS版本检查

id view = [tableViewCellInstance superview];

while (view && [view isKindOfClass:[UITableView class]] == NO) {
    view = [view superview]; 
}

    UITableView *tableView = (UITableView *)view;
Run Code Online (Sandbox Code Playgroud)

  • 我建议在单元格中添加对tableview的弱引用,以避免在将来的更新中出现兼容性问题. (2认同)
  • 简单地创建一个实际上包含指向tableview的指针的弱属性会更好.在子类`@property(弱,非原子)UITableView*tableView;`和`tableView:cellForRowAtIndexPath:`只需设置`cell.tableView = tableView;`. (2认同)

KGS*_*-12 48

在iOS7中,beta 5 UITableViewWrapperView是a的超级视图UITableViewCell.也是UITableViewa的超级视图UITableViewWrapperView.

因此,对于iOS 7,解决方案是

UITableView *tableView = (UITableView *)cell.superview.superview;

因此,对于iOS 6以下的iOS解决方案

UITableView *tableView = (UITableView *)cell.superview;

  • 哦,伙计,这是一个残酷的API改变.如果你同时支持6和7,那么苹果的分支最佳实践是什么? (5认同)
  • 为此在UIView上写一个递归类别.您无需检查版本; 只需调用superview,直到找到表格视图单元格或视图堆栈的顶部.这是我在iOS 6中使用的,它在iOS 7中没有修改就可以工作.并且应该在iOS 8中工作. (2认同)

Ork*_*nov 34

Swift 3扩展

递归

extension UIView {
    func parentView<T: UIView>(of type: T.Type) -> T? {
        guard let view = superview else {
            return nil
        } 
        return (view as? T) ?? view.parentView(of: T.self)
    }
}

extension UITableViewCell {
    var tableView: UITableView? {
        return parentView(of: UITableView.self)
    }
}
Run Code Online (Sandbox Code Playgroud)

使用循环

extension UITableViewCell {
    var tableView: UITableView? {
        var view = superview
        while let v = view, v.isKind(of: UITableView.self) == false {
            view = v.superview
        }
        return view as? UITableView
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @thibautnoah 在展开之前有一个 `view != nil` 检查。不过更新为更干净的代码 (2认同)

mem*_*ons 24

在iOS7之前,单元格的superview是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
Run Code Online (Sandbox Code Playgroud)

这是使用的一个很好的替代品cell.superview,可以轻松地重构现有代码 - 只需搜索和替换[cell relatedTable],并抛出一个断言,以确保如果视图层次结构在未来发生变化或恢复,它将立即显示在你的测试中.

解决方案#2:添加弱UITableView引用UITableViewCell

@interface SOUITableViewCell

   @property (weak, nonatomic) UITableView *tableView;

@end
Run Code Online (Sandbox Code Playgroud)

这是一个更好的设计,但它需要更多的代码重构才能在现有项目中使用.在您tableView:cellForRowAtIndexPath使用SOUITableViewCell作为您的单元类或确保您的自定义单元类是子类SOUITableViewCell并将tableView分配给单元格的tableView属性.在单元格内,您可以使用参考包含的tableview self.tableView.


Her*_*ker 7

如果它是可见的,那么它有一个超级视图.而且......惊喜...... superview是一个UITableView对象.

但是,拥有超级视图并不能保证在屏幕上显示.但UITableView提供了确定哪些单元格可见的方法.

不,没有从单元格到表格的专用引用.但是当你继承UITableViewCell时,你可以引入一个并在创建时设置它.(在我想到子视图层次结构之前,我自己做了很多.)

iOS7更新: Apple在此更改了子视图层次结构.像往常一样,在处理未详细记录的事物时,总会有变化的风险.在最终找到UITableView对象之前,"爬行"视图层次结构是非常安全的.

  • 这在iOS7中已不再适用,在iOS7 beta5中,UITableViewWrapperView是UITableViewCell的超级视图......现在让我遇到问题 (14认同)

Meh*_*zor 7

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
    }
}
Run Code Online (Sandbox Code Playgroud)

或更紧凑(感谢kabiroberai):

import UIKit

extension UIView {
    func lookForSuperviewOfType<T: UIView>(type: T.Type) -> T? {
        return superview as? T ?? superview?.superviewOfType(type)
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的单元格中,您只需将其调用:

let tableView = self.lookForSuperviewOfType(UITableView)
// Here we go
Run Code Online (Sandbox Code Playgroud)

请注意,只有在执行cellForRowAtIndexPath之后才在UITableView上添加UITableViewCell.


Jav*_*oto 6

无论你最终通过调用超级视图或通过响应者链来做什么都将是非常脆弱的.如果单元格想知道某些内容,最好的方法是将对象传递给响应某个方法的单元格,该方法可以回答单元格想要问的问题,并让控制器实现确定要回答的内容的逻辑(根据你的问题,我想细胞想知道某些东西是否可见).

在单元格中创建委托协议,在tableViewController中设置单元格的委托,并在tableViewCotroller中移动所有ui"控制"逻辑.

表视图单元格应该是仅显示信息的dum视图.


bol*_*iva 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
Run Code Online (Sandbox Code Playgroud)

最好,