2015-03-10 4 views
0

Ситуация:Crash - UITableViewCell подкласс KVO'ing UITableView.panGestureRecogonizer.state

Я подклассов UITableViewCell, потому что мне нужно добавить пользовательские кнопки действий по обе стороны от UITableViewCell. Есть определенные ситуации, когда мне нужно вернуть UITableView в нормальное состояние (скрыть пользовательские кнопки действий). , например. Когда пользователь прокручивается вверх в UITableView. Для этого я добавляю свой пользовательский UITableViewCell в качестве наблюдателя из состояния UIPangestureRecognizer, содержащего UITableView.

Проблема:

Когда суя UIViewController, который содержит UITableView и пользовательские UITableViewCells я получаю следующее сообщение об ошибке:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x7b21b920 of class UIScrollViewPanGestureRecognizer was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0xb83618, Property: 0x7b3e13b0> Context: 0xb83618, Property: 0x7b3e13b0> Context: 0xb83618, Property: 0x7b3e13b0> Context: 0xb83618, Property: 0x7b3e13b0>)'

который, очевидно, о том, что UIPanGestureRecognizer в настоящее время освобождаться до пользовательских UITableViewCell-х находятся.

Вопрос:

Где я должен удалить пользовательские UITableViewCell в качестве наблюдателя UIPanGestureRecognizer в UITableView, чтобы я не столкнуться это исключение?

Код:(.. Я надеюсь, что это не слишком много кода, чтобы прочесать я прошу прощения, если он есть)

CustomUITableViewCell.m

#pragma mark - Setter Methods 

- (void)setContainingTableView:(UITableView *)containingTableView 
{ 
    if (self.isObservingContainingTableViewPanGestureRecognizer) 
    { 
     self.observingContainingTableViewPanGestureRecognizer = NO; 

     [_containingTableView.panGestureRecognizer removeObserver:self forKeyPath:kUITableViewPanGestureRecognizerStateKeyPath]; 
    } 

    _containingTableView = containingTableView; 

    if (containingTableView) 
    { 
     self.observingContainingTableViewPanGestureRecognizer = YES; 

     [containingTableView.panGestureRecognizer addObserver:self forKeyPath:kUITableViewPanGestureRecognizerStateKeyPath options:0 context:UITableViewPanGestureRecogonizerContext]; 
    } 
} 

#pragma mark - 


#pragma mark - Overrides 

- (void)didMoveToSuperview 
{ 
    [super didMoveToSuperview]; 

    self.containingTableView = nil; 

    UIView * view = self.superview; 

    while (view) 
    { 
     if ([view isKindOfClass:[UITableView class]]) 
     { 
      self.containingTableView = (UITableView *)view; 
      break; 
     } 

     view = view.superview; 
    } 
} 

- (void)dealloc 
{ 
    self.containingTableView = nil; 
} 

#pragma mark - 

#pragma mark - Key Value Observing 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if (context == UITableViewPanGestureRecogonizerContext) 
    { 
     if ([keyPath isEqual:kUITableViewPanGestureRecognizerStateKeyPath]) 
     { 
      UIPanGestureRecognizer * panGestureRecognizer = (UIPanGestureRecognizer *)object; 

      if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) 
      { 
       CGPoint velocity = [panGestureRecognizer velocityInView:self.contentCellView]; 

       if (fabs(velocity.y) >= fabs(velocity.x)) 
       { 
        [self.scrollView setContentOffset:CGPointZero animated:YES]; 
       } 
      } 
     } 
    } 
    else { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
    } 
} 

#pragma mark - 

Как всегда, любая помощь очень ценится! Кроме того, если кому-то нужна дополнительная информация, пожалуйста, дайте мне знать.

EDIT:

Как ни странно, пользовательский метод dealloc UITableViewCell, называется и обычай UITableViewCell удаляется в качестве наблюдателя, прежде чем я исключение выбрасывается.

+0

в readyForReuse ?? – HMHero

+0

@HMHero, я получаю такое же исключение, если удалить пользовательский UITableViewCell в качестве наблюдателя в prepareForReuse. – Jonathan

ответ

1

Оказалось, что мне нужно сохранить ссылку на UIPanGestureRecognizer UITableView. Скорее всего, я закончу подклассификацию UITableView, чтобы устранить некоторые из осложнений.

0

UITableView является подклассом UIScrollView. Если вы хотите, чтобы определить, когда пользователь его прокрутки вы можете использовать Scrollview метод делегата:

  • (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
+0

Это потребует от меня подкласса UITableView, хотя этого я и стараюсь избежать. – Jonathan

+1

Нет необходимости в подклассе tableview. Просто реализуйте этот метод в контроллере, который является делегатом для вашего табличного представления. – sanjana

+0

А, это хорошая идея, но я хотел бы сохранить эту логику в пользовательском подклассе UITableViewCell. – Jonathan

0

Я думаю, вы должны пройти слабую ссылку зрения таблицы в ячейку (в качестве делегата) в cellForRowAtIndexPath, а не ищет Tableview в didMoveToSuperview. В целом, я не думаю, что было бы неплохо иметь наблюдателя жестов в виде таблицы в ячейке. Однако, если вы действительно этого хотите, убедитесь, что вы правильно зарегистрировали/отменили регистрацию. Также убедитесь, что значение isObservingContainingTableViewPanGestureRecognizer является правильным, когда ячейка повторно используется.

Смежные вопросы