Skip to content
This repository has been archived by the owner on Mar 3, 2020. It is now read-only.

self.KVOControllerNonRetaining observe:self crash #140

Open
GitHubXuLiying opened this issue Oct 17, 2018 · 4 comments
Open

self.KVOControllerNonRetaining observe:self crash #140

GitHubXuLiying opened this issue Oct 17, 2018 · 4 comments

Comments

@GitHubXuLiying
Copy link

GitHubXuLiying commented Oct 17, 2018

System version less than iOS 11

[self.KVOControllerNonRetaining observe:self keyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld block:^(id _Nullable observer, id _Nonnull object, NSDictionary<NSString *,id> * _Nonnull change) {
NSLog(@"xly--%@",change);
}];

  • (void)dealloc {
    NSLog(@"xly--%@",@"dealloc");
    [self.KVOControllerNonRetaining unobserveAll];
    }

pop crash

2018-10-17 14:40:41.390 TestField[71971:8049984] xly--dealloc
2018-10-17 14:40:45.767 TestField[71971:8049984] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x7fa168e04230 of class TestViewController was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x60000003a4c0> (
<NSKeyValueObservance 0x608000244470: Observer: 0x60800009bda0, Key path: name, Options: <New: YES, Old: YES, Prior: NO> Context: 0x60800007ffc0, Property: 0x6080002422e0>
)'

@KosmicTask
Copy link

KosmicTask commented Oct 24, 2018

I am seeing the exactly same issue with KVOControllerNonRetaining prior to macOS 10.12 on binaries build on macOS 10.14. No issue on 10.13 and 10.14 though.

Looking at the header for -KVOControllerNonRetaining

When not retaining observed objects, special care must be taken to remove observation info prior to deallocation of the observed object.

Note the prior in the above. If we are observing self we must remove the observer prior to deallocating self.

Note that this is different to vanilla KVO. The reason for this is that the reference to self is kept in a weak referencing NSMapTable. When -dealloc is called on the observer the weak reference in the mapTable has already gone to nil so the observation does not get removed.

The funky part seems to be that the Cocoa KVO machinery post 10.12 seems to be able to tolerate the surviving observation during -dealloc - perhaps it is simply smart enough to say, well I am deallocating while observing myself (and there is no danger of self receiving any further messages from self).

So personally I would consider -KVOControllerNonRetaining a bit of a poisoned chalice. It will work fine for self observation on some platforms and fail on others. For self observation vanilla KVO is the way forward.

@ApesTalk
Copy link

ApesTalk commented Dec 19, 2018

Same issue here, on iOS 10.3.3.

@iCodeWoods
Copy link

Or, you could just remove the unobserveAll call. Because KVOController uses weak references, it's safe to just deallocate with it.

I also encountered this problem, but i see a answer above
#46 (comment)

@AlfyYan
Copy link

AlfyYan commented Jan 17, 2020

Add the code below and it works fine:

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    
    // fix: iOS 10 crash
    [self.KVOControllerNonRetaining unobserveAll];
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants