• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
OS X 10.10 KVO default behaviour change when observers not removed
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

OS X 10.10 KVO default behaviour change when observers not removed


  • Subject: OS X 10.10 KVO default behaviour change when observers not removed
  • From: Jonathan Mitchell <email@hidden>
  • Date: Sat, 07 Feb 2015 21:57:56 +0000

Jens mentioned in a previous thread that he was not quite sure whether to always remove observations or not.
This was bugging me. I always did it, though more out of habit than absolute conviction.
The code below confirms that not removing the observation prior to deallocating the observing object really is toxic.

As shown if linked on OS X 10.9 the code below may run to completion or may terminate with an access violation (YMMV).
If the code completes a warning is logged stating that the observed object still has registered observers.
When we mutate the observed key path the deallocated instance gets messaged, which may or may not be terminal.

If linked on OS X 10.10 then the code never completes.
Either it terminates due to an access violation or it aborts as the previous console warning is now a NSInternalInconsistencyException and the thread aborts.

This issue can lurk in code without causing problems if the observed and observing objects tend to get deallocated together.
One can easily see how refactoring could cause the observed object to outlive its observer and produce instability.

#import <Foundation/Foundation.h>

@interface MGSObservedObject : NSObject
@property (strong) NSString *name;
@end

@interface MGSObservingObject : NSObject
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MGSObservedObject *observedObject = [MGSObservedObject new];
        MGSObservingObject *observingObject = [MGSObservingObject new];

        [observedObject addObserver:observingObject forKeyPath:@"name" options:0 context:NULL];
        observedObject.name = @"Laura Palmer";

        BOOL removeObservation = NO;
        if (removeObservation) {
            [observedObject removeObserver:observingObject forKeyPath:@"name" context:NULL];
        }

        BOOL deallocObservingObject = YES;
        if (deallocObservingObject)  {
            observingObject = nil;
        }

        BOOL pokeObservedObject = YES;
        if (pokeObservedObject) {
            observedObject.name = @"Ronette Pulaski"; // on 10.9 observer may still register change or we may crash, who knows!
        }
    }
    return 0;
}

@implementation MGSObservingObject

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"observed : %@", [object valueForKeyPath:keyPath]);
}

@end


@implementation MGSObservedObject
@end















_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden


  • Prev by Date: Identify all open files of current OS X process
  • Next by Date: Re: ARC dealloc best pratice
  • Previous by thread: Re: Identify all open files of current OS X process
  • Next by thread: Trying to create a circular button with image, but the image wasn't clipped automatically
  • Index(es):
    • Date
    • Thread