9

I'm getting the UITableViewCell a UIButton belongs to like this:

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

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

And it works fine in anything before iOS 7. But gives me:

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

if I run the app in iOS 7. BUT if I do:

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

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

Then it works in iOS 7 but not earlier?!?!?!

I'm circumventing the issue by doing this:

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);

but WTF is going on!? Does anyone know why this happens?

Thanks!

rmaddy
  • 307,833
  • 40
  • 508
  • 550
thehindutimes
  • 321
  • 1
  • 6
  • 19

5 Answers5

27

A better solution is to add a category for UIView(SuperView), and calling it by:

UITableViewCell *cell = [button findSuperViewWithClass:[UITableViewCell class]]

This way, your code works for all future and past iOS versions

@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
Thomas Keuleers
  • 6,015
  • 2
  • 31
  • 35
  • 9
    This code can be improved by adding a `break` once you find the matching superview. No need to go all the way up to the window every time. – rmaddy Sep 24 '13 at 01:22
13

The best way to do this is:

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
UITableViewCell *cell = (UITableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];
Matt Hudson
  • 7,299
  • 5
  • 48
  • 65
3

To complete the answer of @thomas-keuleers this is the swift method:

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
    }

}

and you simply call like that:

child.findSuperViewWithClass(TableViewCell)
Armanoide
  • 1,250
  • 14
  • 30
0

A shorter Version in swift 5

extension UIView {
   var xsuperView = self.superview

   while xsuperView != nil {
        if let superView = xsuperView.self as? T {
            return superView
        } else {
            xsuperView = xsuperView?.superview
        }
    }
}
PMW
  • 11
  • 3
-2
if ([[button superView] isKindOfClass:[UITableViewCell class]]) {

}

else //check next :
CW0007007
  • 5,642
  • 3
  • 25
  • 30