Получение UITableViewCell с супервизором в iOS 7

Я получаю UITableViewCell, которому принадлежит UIButton:

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

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

И он отлично работает во всем до iOS 7. Но дает мне:

[Элемент UITableViewCellScrollView]: нераспознанный селектор отправлен экземпляру 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);

но WTF происходит!? кто-нибудь знает, почему это произошло?

Спасибо!


person thehindutimes    schedule 23.09.2013    source источник
comment
Ваш код зависел от структуры частного подпредставления UITableViewCell. Очевидно, что эта структура изменилась в iOS 7. Есть гораздо более безопасные способы делать то, что вы хотите. И ваш новый код сломается под iOS 7.1 и iOS 8.   -  person rmaddy    schedule 23.09.2013
comment
@rmaddy Какой способ безопаснее?   -  person Mundi    schedule 23.09.2013
comment
Вы можете перебирать суперпредставления, проверяя, относятся ли они к типу класса UITableViewCell, а затем возвращать это представление? Смотрите ответ:   -  person CW0007007    schedule 23.09.2013
comment
@thehindutimes - Да, то, что сказал CW0007007.   -  person rmaddy    schedule 23.09.2013
comment
Правда, всем спасибо за отзывы!   -  person thehindutimes    schedule 24.09.2013


Ответы (4)


Лучшее решение — добавить категорию для 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
person Thomas Keuleers    schedule 23.09.2013
comment
Этот код можно улучшить, добавив break, как только вы найдете соответствующий супервизор. Не нужно каждый раз подходить к окну. - person rmaddy; 24.09.2013

Лучший способ сделать это:

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
UITableViewCell *cell = (UITableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];
person Matt Hudson    schedule 10.12.2013
comment
Лучший ответ, очень надежное решение - person Gennadiy Ryabkin; 31.03.2015

Чтобы завершить ответ @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)
person Armanoide    schedule 05.06.2015
comment
child.findSuperViewWithClass (TableViewCell.self) - person sasquatch; 27.10.2017

Более короткая версия в Swift 5

extension UIView {
   var xsuperView = self.superview

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