ios - 崩溃 - UITableViewCell 子类 KVO'ing UITableView.panGestureRecogonizer.state

标签 ios key-value-observing

情况:

我已经将 UITableViewCell 子类化,因为我需要在 UITableViewCell 的任一侧添加自定义操作按钮。在某些情况下,我需要将 UITableView 设置回正常状态(隐藏自定义操作按钮)。 例如 当用户在 UITableView 中向上滚动时。为此,我将我的自定义 UITableViewCell 添加为包含 UITableView 的 UIPangestureRecognizer 状态的观察者。

问题:

弹出包含 UITableView 和自定义 UITableViewCells 的 UIViewController 时,我收到以下错误:

*** 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 之前被释放。

问题:

作为 UITableView 的 UIPanGestureRecognizer 的观察者,我应该在哪里删除自定义 UITableViewCell,这样我就不会遇到这个异常?

代码: (我希望这不是太多需要梳理的代码。如果是的话,我深表歉意。)

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 - 

一如既往,非常感谢任何帮助!另外,如果有人需要更多信息,请告诉我。

编辑:

奇怪的是,自定义 UITableViewCell 的 dealloc 方法被调用,并且在抛出异常之前自定义 UITableViewCell 作为观察者被删除。

最佳答案

事实证明,我需要保留对 UITableView 的 UIPanGestureRecognizer 的引用。我很可能最终会子类化 UITableView 以消除一些复杂情况。

关于ios - 崩溃 - UITableViewCell 子类 KVO'ing UITableView.panGestureRecogonizer.state,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28972872/

相关文章:

ios - UIView 动画 layoutIfneeded 不工作

ios - 要求用户在注册过程后允许推送通知

javascript - Angular 2+ 检测服务内部的对象属性更改

cocoa - "to-many"关系是否应该建模为属性?

cocoa - NSCollectionView 中的数据绑定(bind)

ios - GMSMapView 总是显示相同的位置 iOS

ios - 使用带有 NavigationView 的 ScrollView 我得到空白的灰色空间

ios - 无法更新从未插入的对象

cocoa - 实现符合键值观察的普通数据对象的最*简单*方法是什么?

objective-c - 隐藏由可变数据支持的不可变属性并支持 Objective-C 中符合 KVO 的集合的最佳模式是什么?