IOS 8: - [UITableViewWrapperView textField]: непризнанный селектор, отправленный в экземпляр

Привет. Я тестировал свое приложение на iOS 6, 7 и теперь 8 (бета-версия 5). Мой UITableView с пользовательским UITableViewCell работает нормально на 6 и 7. Однако на iOS 8 я получаю сбой при попытке получить доступ к подсмотру (текстовому полю) ячейки.

Мне известно о том, что в iOS 7 есть другой вид в иерархии ячеек. Как ни странно, похоже, что это не так в iOS 8. Вот код, который я использую:

    //Get the cell
    CustomCell *cell = nil;

    //NOTE: GradingTableViewCell > UITableViewCellScrollView (iOS 7+ ONLY) > UITableViewCellContentView > UIButton (sender)
    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
        cell = (CustomCell *)sender.superview.superview;
    } else {
        cell = (CustomCell *)sender.superview.superview.superview;
    }

    //Get the cell index path
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

    //etc.

    NSLog(@"%@", cell.textField); //<---Crashes here

Итак, как вы можете видеть, я учитываю дополнительный вид в iOS 7. После добавления некоторых точек останова и более пристального взгляда на переменные я вижу, что cell существует, но все подзаголовки, которые он имеет в файл интерфейса (который связан) - включая textField - - nil. В указанной строке я получаю следующий журнал сбоев:

-[UITableViewWrapperView textField]: unrecognized selector sent to instance 0x12c651430

Я изучил это дальше, и я нашел это:

Изменение оператора else идентично предыдущей строке избавляет от сбоя, и приложение работает нормально (используя sender.superview.superview, как в iOS 6).

Это не имеет никакого смысла для меня. Apple вернула иерархию UITableViewCell к иерархии iOS 6, или я что-то упустил? Спасибо!

Ответ 1

Я столкнулся с той же проблемой. Здесь более надежный метод:

UITextField* textField = (UITextField*)sender;
NSIndexPath* indexPath = [self.tableView indexPathForRowAtPoint:[self.tableView convertPoint:textField.center fromView:textField.superview]];

Это будет работать независимо от базовой иерархии представлений UITableViewCell.

Ответ 2

Различные версии iOs имеют разные реализации UITableView или UITableViewController, поскольку вам нужно будет выполнять итерацию через superviews, пока вы не найдете нужный класс представления, вместо того чтобы полагаться на него как на N-й супервизор.

Ответ 3

У меня также была такая же проблема на iOS8 с получением UITableViewCell через супервизор из дочернего представления. Это то, что я придумал для поддержки iOS7 и iOS8.

-(void)thumbTapped:(UITapGestureRecognizer*)recognizer {
    NSLog(@"Image inside a tableview cell is tapped.");

    UIImageView *mediaThumb = (UIImageView*)recognizer.view;
    UITableViewCell* cell;
    // get the index of container cell row
    // bug with ios7 vs ios8 with superview level!! :(
    /*** For your situation the level of superview will depend on the design structure ***/
    // The rule of thumb is for ios7 it need an extra superview
    if (SYSTEM_VERSION_LESS_THAN(@"8.0")) { // iOS 7
        cell = (UITableViewCell*)mediaThumb.superview.superview.superview.superview;
    } else { // iOS 8
        cell = (UITableViewCell*)mediaThumb.superview.superview.superview;
    }
}

Чтобы уточнить, в cellForRowAtIndexPath я назначил распознаватель жестов. Оригинальный дизайн очень сложный в раскадровке с множеством подзонов, кнопок и т.д.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MediaCell" forIndexPath:indexPath];
    .......    
    UIImageView *mediaImage = ............
    .....................................
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(thumbTapped:)];
    [mediaImage addGestureRecognizer:tapGestureRecognizer];

    return cell;
}