在iOS 7中获取带有父视图的UITableViewCell

9
我这样获取UITableViewCell中的UIButton:

-(void)buttonHandler:(UIButton *)button {

    OrderCell *cell = [[button superview] superview];
    NSLog(@"cell.item = %@", cell.item.text);

这段代码在iOS 7之前版本中运行正常,但是在iOS 7上会出现以下错误:

[UITableViewCellScrollView item]: unrecognized selector sent to instance 0x17ae2cf0

如果您想在iOS 7上运行该应用程序,可以尝试如下操作:

-(void)buttonHandler:(UIButton *)button {

    OrderCell *cell = [[[button superview] superview] superview];
    NSLog(@"cell.item = %@", cell.item.text);

那么它在iOS 7上可以工作,但之前的版本就不行?!?!

我通过以下方式规避了这个问题:

OrderCell *cell;
if([[[UIDevice currentDevice] systemVersion] isEqualToString:@"7.0"])
    cell = [[[button superview] superview] superview];
else
    cell = [[button superview] superview];

NSLog(@"cell.item = %@", cell.item.text);

但是到底发生了什么事情!?有人知道为什么会这样吗?

谢谢!


2
你的代码依赖于UITableViewCell的私有子视图结构。显然,这个结构在iOS 7中已经改变了。有更安全的方法来实现你想要的功能。而且你的新代码将在iOS 7.1和iOS 8下出现问题。 - rmaddy
@rmaddy 什么是更安全的方式? - Mundi
1
你可以遍历父视图,检查它们是否属于UITableViewCell类类型,然后返回该视图?参见答案: - CW0007007
@印度教徒时报 - 是的,就像CW0007007所说的那样。 - rmaddy
5个回答

27

更好的解决方案是为UIView(SuperView)添加一个类别,并通过以下方式调用:

UITableViewCell *cell = [button findSuperViewWithClass:[UITableViewCell class]]
这样,您的代码就可以在所有未来和过去的iOS版本中运行。
@interface UIView (SuperView)

- (UIView *)findSuperViewWithClass:(Class)superViewClass;

@end


@implementation UIView (SuperView)

- (UIView *)findSuperViewWithClass:(Class)superViewClass {

    UIView *superView = self.superview;
    UIView *foundSuperView = nil;

    while (nil != superView && nil == foundSuperView) {
        if ([superView isKindOfClass:superViewClass]) {
            foundSuperView = superView;
        } else {
            superView = superView.superview;
        }
    }
    return foundSuperView;
}
@end

9
如果找到匹配的父视图,可以通过添加break来改进此代码。每次都不需要一直往上走到窗口。 - rmaddy

13

最好的方法是:

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
UITableViewCell *cell = (UITableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];

最佳答案,非常可靠的决定。 - Henadzi Rabkin

3
为了完整回答 @thomas-keuleers 的问题,以下是快速方法:

完成 @thomas-keuleers 的回答,这是一种迅捷的方法:

extension UIView {

    func findSuperViewWithClass<T>(superViewClass : T.Type) -> UIView? {

        var xsuperView : UIView!  = self.superview!
        var foundSuperView : UIView!

        while (xsuperView != nil && foundSuperView == nil) {

            if xsuperView.self is T {
                foundSuperView = xsuperView
            } else {
                xsuperView = xsuperView.superview
            }
        }
        return foundSuperView
    }

}

你只需要像这样调用:

child.findSuperViewWithClass(TableViewCell)

child.findSuperViewWithClass(TableViewCell.self) - saurabh

0

Swift 5 中的简短版本

extension UIView {
   var xsuperView = self.superview

   while xsuperView != nil {
        if let superView = xsuperView.self as? T {
            return superView
        } else {
            xsuperView = xsuperView?.superview
        }
    }
}

-2
if ([[button superView] isKindOfClass:[UITableViewCell class]]) {

}

else //check next :

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接