2016-06-12 132 views
1

我在控制器中有滚动视图。滚动视图有一个子视图。子视图同时是滚动视图的观察者。当子视图willMoveToSuperview:调用时,我删除观察者。但是当控制器解散时,应用程序崩溃了。下面是范例代码:删除KVO观察者时APP崩溃

@interface MyView : UIView 

@property (nonatomic, weak) UIScrollView *scrollView; 

@end 

@implementation MyView 

- (instancetype)initWithFrame:(CGRect)frame scrollView:(UIScrollView *)scrollView { 
    self = [super initWithFrame:frame]; 
    if (self) { 
     self.scrollView = scrollView; 
     [scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; 
    } 
    return self; 
} 

- (void)willMoveToSuperview:(UIView *)newSuperview { 
    [super willMoveToSuperview:newSuperview]; 

    if (!newSuperview) { 
     [self.scrollView removeObserver:self forKeyPath:@"contentOffset"]; 
     self.scrollView = nil; 
    } 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { 
} 

@end 

@interface SecondViewController() 

@end 

@implementation SecondViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; 
    scrollView.backgroundColor = [UIColor whiteColor]; 
    [self.view addSubview:scrollView]; 

    MyView *view = [[MyView alloc] initWithFrame:CGRectMake(100, 200, 100, 100) scrollView:scrollView]; 
    [scrollView addSubview:view]; 
} 

@end 

当我在willMoveToSuperview打印self.scrollView,它显示为空。当我将MyView中的属性scrollView更改为unsafe_unretained时,应用程序不会崩溃。 所以我很困惑。为什么不弱scrollView工作。我是否在读取悬挂指针时scrollView是unsafe_unretained?这种情况有更好的解决办法吗?

+0

哇是坠机? EXC_BAD_ACCESS? –

+0

在@try中删除代码catch – Nick

+0

@AndreyChernukha崩溃与未调用'removeObserver:forKeyPath:' '2016-06-12 22:39:53.752 ScrollView [20987:7043889] ***终止应用,原因是未捕获的异常'NSInternalInconsistencyException',原因:'UIScrollView类的实例0x7fd01b824400被释放,而键值观察者仍在注册它。现有的观测信息:的语境:为0x0,属性:> )” ' – Bing

回答

1

的问题在这里是由时间willMoveToSuperview称为scrollViewweak指针已经nil(释放)。 但它认为scrollView不完全释放(内存不释放),这就是为什么当你使用unsafe_unretained引用删除观察者它以某种方式工作。但它是一个悬而未决的指针引用,你不应该依赖它。

+1

我觉得在willMoveToSuperview中的removeObserver可能是一个糟糕的设计。 – Bing

+0

是的,你不应该观察任何你不能确定它何时被释放的对象。 – srvv