如何从UITableViewCell获取UITableView?

时间:2013-03-29 21:26:32

标签: iphone ios objective-c xcode tableview

我有一个UITableViewCell链接到一个对象,我需要判断该单元格是否可见。根据我所做的研究,这意味着我需要以某种方式访问​​包含它的UITableView(从那里,有几种方法可以检查它是否可见)。所以我想知道UITableViewCell是否有指向UITableView的指针,或者是否还有其他方法可以从单元格中获取指针?

21 个答案:

答案 0 :(得分:150)

避免iOS版本检查

id view = [tableViewCellInstance superview];

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

    UITableView *tableView = (UITableView *)view;

答案 1 :(得分:48)

在iOS7测试版中,UITableViewWrapperViewUITableViewCell的超级视图。 另外UITableViewUITableViewWrapperView的超级视图。

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

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

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

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

答案 2 :(得分:31)

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
    }
}

答案 3 :(得分:24)

在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],并输入断言以确保如果查看层次结构更改或将来还原将在测试中立即显示。

解决方案#2:向UITableView

添加弱UITableViewCell引用
@interface SOUITableViewCell

   @property (weak, nonatomic) UITableView *tableView;

@end

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

答案 4 :(得分: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
    }
}

或更紧凑(感谢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

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

答案 5 :(得分:7)

如果可见则会有超级视图。而且......惊喜...... superview是一个UITableView对象。

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

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

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

答案 6 :(得分: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 :(得分:6)

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

在单元格中创建委托协议,将tableViewController设置为单元格的委托,并在tableViewCotroller中移动所有ui“控制”逻辑。

表格视图单元格应为dum视图,仅显示信息。

答案 8 :(得分:3)

以下是基于上述答案的 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
    }
}

希望这有帮助:)

答案 9 :(得分:2)

我的解决方案基于Gabe的建议,即UITableViewWrapperView对象是iOS7 beta5中UITableViewCell对象的超级视图。

子类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];
}

答案 10 :(得分:2)

我从上面的答案中借用并修改了一点,并提出了以下代码段。

- (id)recursivelyFindSuperViewWithClass:(Class)clazz fromView:(id)containedView {
    id containingView = [containedView superview];
    while (containingView && ![containingView isKindOfClass:[clazz class]]) {
        containingView = [containingView superview];
    }
    return containingView;
}

在其他场合,传递类可以灵活地遍历和获取UITableView以外的视图。

答案 11 :(得分:2)

我对这个问题的解决方案有点类似于其他解决方案,但使用优雅的for循环并且很短。它也应该是面向未来的:

- (UITableView *)tableView
{
    UIView *view;
    for (view = self.superview; ![view isKindOfClass:UITableView.class]; view = view.superview);
    return (UITableView *)view;
}

答案 12 :(得分:2)

UITableView *tv = (UITableView *) self.superview.superview;
BuyListController *vc = (BuyListController *) tv.dataSource;

答案 13 :(得分:1)

尝试使用[“UItableViewvariable”visibleCells]而不是superview。

我在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 
    }
  }
}

像魅力一样。

答案 14 :(得分:1)

经过最低限度的测试,但这个非通用的Swift 3示例似乎有效:

extension ViewController: NSTouchBarDelegate  {
    override func makeTouchBar() -> NSTouchBar? {

        let touchBar = NSTouchBar()

        touchBar.delegate = self

        touchBar.customizationIdentifier = .myBar

        touchBar.defaultItemIdentifiers = [.itemId1, 
                .flexibleSpace, 
                .itemId2, 
                .itemId3, 
                .flexibleSpace, 
                .candidateList]

        touchBar.customizationAllowedItemIdentifiers = [.itemId1]

        return touchBar
    }
}

答案 15 :(得分:0)

来自@idris回答 我在Swift中为UITableViewCell编写了一个扩展

extension UITableViewCell {
func relatedTableView() -> UITableView? {
    var view = self.superview
    while view != nil && !(view is UITableView) {
        view = view?.superview
    }

    guard let tableView = view as? UITableView else { return nil }
    return tableView
}

答案 16 :(得分:0)

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
    }
}

答案 17 :(得分:0)

您可以使用一行代码获取它。

UITableView *tableView = (UITableView *)[[cell superview] superview];

答案 18 :(得分:0)

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 :(得分:0)

我建议您以这种方式遍历视图层次结构以查找父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再次更改视图层次结构时,您的代码将会中断

遍历层次结构的

Another answer是递归的。

答案 20 :(得分:0)

此代码`UITableView *tblView=[cell superview];将为您提供包含tabe视图单元格的UItableview实例