我需要检测tableview contentOffset的变化,所以我使用KVO,一切都很完美。在同一个视图控制器中,我也有一个UIActivityViewController服务。 如果我使用uiactivityviewcontroller中的服务,然后,在解雇后,我弹出视图控制器,我得到以下错误...
* frame #0: 0x0000000183071280 CoreFoundation`___forwarding___ + 736
frame #1: 0x0000000182f9108c CoreFoundation`__forwarding_prep_0___ + 92
frame #2: 0x0000000183b2e7d0 Foundation`NSKeyValuePushPendingNotificationPerThread + 340
frame #3: 0x0000000183b19068 Foundation`NSKeyValueWillChange + 532
frame #4: 0x0000000183b023a8 Foundation`-[NSObject(NSKeyValueObserverNotification) willChangeValueForKey:] + 236
frame #5: 0x0000000183bc9148 Foundation`_NSSetPointValueAndNotify + 116
frame #6: 0x00000001863126c0 UIKit`-[UIScrollView(UIScrollViewInternal) _adjustContentOffsetIfNecessary] + 864
frame #7: 0x0000000186116a0c UIKit`-[UIScrollView(UIScrollViewInternal) _stopScrollingNotify:pin:tramplingDragFlags:] + 352
frame #8: 0x0000000186116864 UIKit`-[UIScrollView removeFromSuperview] + 44
frame #9: 0x000000018603377c UIKit`-[UIView dealloc] + 424
frame #10: 0x0000000182f69ad4 CoreFoundation`CFRelease + 468
frame #11: 0x0000000182f75ec0 CoreFoundation`-[__NSArrayM dealloc] + 156
frame #12: 0x000000018f58d474 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 524
frame #13: 0x0000000182f6d438 CoreFoundation`_CFAutoreleasePoolPop + 28
frame #14: 0x000000018302c974 CoreFoundation`__CFRunLoopRun + 1460
frame #15: 0x0000000182f6d6d0 CoreFoundation`CFRunLoopRunSpecific + 452
frame #16: 0x0000000188c51c0c GraphicsServices`GSEventRunModal + 168
frame #17: 0x000000018609efdc UIKit`UIApplicationMain + 1156
要添加或删除kvo,请使用以下行
- (void)viewWillAppear:(BOOL)animated
{
[self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:NULL];
}
- (void)viewWillDisappear:(BOOL)animated
{
[self.tableView removeObserver:self forKeyPath:@"contentOffset"];
}
答案 0 :(得分:3)
你应该有一个状态属性来跟踪你是否添加了你的观察者。当您的活动视图指示器控制器出现时,您可能看不到viewWillDisappear
,即使您在返回时可能会再次调用viewWillAppear
。因此,当您关闭视图控制器时,您已经添加了两次观察者,但只删除了一次。
加入一些NSLog
语句,我敢打赌你会发现你对viewWillDisappear
和viewWillAppear
的调用不平衡(不是你自己的错误)。结果,我敢打赌你添加观察者的次数比你删除的次数多。
通过添加州属性observingContentOffset
,您可以解决此问题:
@property (nonatomic) BOOL observingContentOffset;
然后,您可以使用添加和删除观察者的代码来检查此属性:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated]; // don't forget to call super
if (!self.observingContentOffset) {
[self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:NULL];
self.observingContentOffset = YES;
}
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated]; // don't forget to call super
if (self.observingContentOffset) {
[self.tableView removeObserver:self forKeyPath:@"contentOffset"];
self.observingContentOffset = NO;
}
}
虽然以上内容可以解决您的问题,但我会更进一步,建议您考虑完全退出此KVO代码。由于tableview实际上是滚动视图的子类,因此在设置表视图的委托时,您还要指定基础scrollview的委托。因此,在指定了表视图的委托之后,它还将用作滚动视图委托,您可以简单地实现相关的UIScrollViewDelegate
方法。如果你需要识别每个滚动事件,这可能是一个比KVO更强大的技术(它也巧合地消除了你原来的问题)。如果您只需要确定何时从视图中删除单元格,iOS 6就会提供一些相关的高级UITableViewDelegate
方法,使其更加轻松。