情况:
我已经将UITableViewCell子类化了,因为我需要在UITableViewCell的任一侧添加自定义操作按钮。在某些情况下,我需要将UITableView设置恢复正常(隐藏自定义操作按钮)。 例如当用户在UITableView中向上滚动时。为此,我将自定义UITableViewCell添加为包含UITableView的UIPangestureRecognizer状态的观察者。
问题:
当弹出包含UITableView和自定义UITableViewCells的UIViewController时,我收到以下错误:
***因未捕获的异常终止应用程序' NSInternalInconsistencyException',原因:'实例0x7b21b920 of 类键UIScrollViewPanGestureRecognizer在键值时被释放 观察员仍在注册。目前的观察信息: (上下文:0xb83618,属性:0x7b3e13b0> 上下文:0xb83618, 物业:0x7b3e13b0> 上下文:0xb83618,属性:0x7b3e13b0>上下文:0xb83618,属性:0x7b3e13b0> )'
显然,在自定义UITableViewCell之前,UIPanGestureRecognizer正在被解除分配。
问题:
我应该在哪里删除自定义UITableViewCell作为UITableView的UIPanGestureRecognizer的观察者,以便我不会遇到此异常?
代码: (我希望这不是太多代码可以梳理。如果是,我道歉。)
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作为观察者删除。
答案 0 :(得分:1)
事实证明我需要保留对UITableView的UIPanGestureRecognizer的引用。我很可能最终会对UITableView进行子类化,以消除一些并发症。
答案 1 :(得分:0)
UITableView是UIScrollView的子类。如果您只想检测用户何时滚动它,您可以使用scrollview委托方法:
- (void)scrollViewWillBeginDragging :( UIScrollView *)scrollView;
答案 2 :(得分:0)
我认为你应该将表视图的弱引用传递给cellForRowAtIndexPath中的cell(作为委托),而不是在didMoveToSuperview中查找tableview。总的来说,我不认为让桌面观察手势观察者进入牢房是一个好主意。但是,如果您确实需要它,请确保正确注册/取消注册。 还要确保isObservingContainingTableViewPanGestureRecognizer标志的初始值在单元格重用时是正确的。