2016-06-12 135 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