2016-06-12 17 views
1

Ich habe eine Bildlaufansicht im Controller. Die Bildlaufansicht hat eine Unteransicht. Die Unteransicht ist gleichzeitig ein Beobachter der Bildlaufansicht. Ich entferne den Beobachter, wenn die Unteransicht willMoveToSuperview: aufgerufen wird. Aber als der Controller entlassen wurde, stürzte die App ab. Hier ist der Beispielcode:APP stürzt ab, wenn KVO-Beobachter entfernen

@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 

Wenn ich self.scrollView in willMoveToSuperview drucken, es null zeigt. Wenn ich die Eigenschaft scrollView in MyView in unsafe_unready ändere, stürzt die App nicht ab. Also ich bin verwirrt. Warum nicht schwach scrollView arbeiten. Lies ich den baumelnden Zeiger, wenn scrollView unsafe_unreadyed ist? Gibt es eine bessere Lösung für diese Situation?

+0

Wha ist der Absturz? EXC_BAD_ACCESS? –

+0

setzen Sie entfernen Code in @try fangen – Nick

+0

@AndreyChernukha der Absturz ist das gleiche wie nicht aufrufen 'removeObserver: forKeyPath:' '2016-06-12 22: 39: 53.752 ScrollView [20987: 7043889] *** App aufgrund beenden Uncaught-Ausnahme 'NSInternalInconsistencyException', Grund: 'Eine Instanz 0x7fd01b824400 der Klasse UIScrollView wurde freigegeben, während Schlüsselwertbeobachter noch bei dieser Instanz registriert waren. Aktuelle Beobachtung Info: ( Kontext: 0x0, Eigentum:> )‘ ' – Bing

Antwort

1

Die Frage ist hier von der Zeit willMoveToSuperview der scrollView genannt wird weak Zeiger ist bereits nil (freigegeben). Aber es denken, scrollView nicht vollständig freigegeben (Speicher nicht freigegeben), das ist, warum, wenn Sie unsafe_unretained Referenz zum Entfernen Beobachter verwenden, funktioniert es irgendwie. Aber es ist ein fliegender Zeiger Verweis und Sie sollten sich nicht darauf verlassen.

+1

Ich denke removeObserver in willMoveToSuperview möglicherweise ein schlechtes Design. – Bing

+0

yeah, Sie sollten kein Objekt beobachten, für das Sie nicht bestimmen können, wann es freigegeben wird. – srvv

Verwandte Themen