So I have a class, CustomCell : UITableViewCell
with a single addObserver:forKeyPath:options:context:
method, called in -awakeFromNib
, and a single removeObserver:forKeyPath:context:
method, called in -dealloc
.
CustomCell.m
static void * const MyClassKVOContext = (void*)&MyClassKVOContext; // unique context
-(void)awakeFromNib
{
[super awakeFromNib];
[self registerAsLocationListener];
}
-(void)registerAsLocationListener
{
if ([self.reuseIdentifier isEqualToString:@"locationcell1"])
{
[[RA_LocationSingleton locationSingleton]
addObserver:self
forKeyPath:@"currentLocation"
options:NSKeyValueObservingOptionNew
context:MyClassKVOContext];
NSLog(@"Registered for currentLocation");
NSLog(@"self.description: %@", [self description]);
}
}
-(void)dealloc
{
if ([self.reuseIdentifier isEqualToString:@"locationcell1"])
{
NSLog(@"Attempting to deregister");
NSlog(@"self.description: %@", [self description]);
[self removeObserver:self
forKeyPath:@"currentLocation"
context:MyClassKVOContext];
}
// [super dealloc]; called automatically, using ARC
}
I get the following log, after loading the view with these cells, then backing out again (triggering the dealloc)
// load view
2014-09-01 14:27:33.704 Rally[2931:60b] Registered for currentLocation
2014-09-01 14:27:33.705 Rally[2931:60b] self.description: <CustomCell: 0x9afa570; baseClass = UITableViewCell; frame = (0 0; 320 44); autoresize = RM+BM; layer = <CALayer: 0x9afa710>>
// exit from view
2014-09-01 14:27:40.867 Rally[2931:60b] Attempting to deregister
2014-09-01 14:27:40.868 Rally[2931:60b] self.description: <CustomCell: 0x9afa570; baseClass = UITableViewCell; frame = (0 231; 320 44); autoresize = W; layer = <CALayer: 0x9afa710>>
2014-09-01 14:27:40.870 Rally[2931:60b] *** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <CustomCell 0x9afa570> for the key path "currentLocation" from <CustomCell 0x9afa570> because it is not registered as an observer.'
*** First throw call stack:
(
0 CoreFoundation 0x026761e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x023f58e5 objc_exception_throw + 44
2 CoreFoundation 0x02675fbb +[NSException raise:format:] + 139
3 Foundation 0x0204346d -[NSObject(NSKeyValueObserverRegistration) _removeObserver:forProperty:] + 538
4 Foundation 0x020431f4 -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] + 105
5 Foundation 0x02043118 -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:context:] + 172
6 Rally 0x00005ac1 -[CustomCell dealloc] + 353
7 UIKit 0x01107b94 -[UIView release] + 89
8 CoreFoundation 0x025f7bf0 CFRelease + 272
9 CoreFoundation 0x0261716e -[__NSArrayM dealloc] + 142
10 libobjc.A.dylib 0x02406692 _ZN11objc_object17sidetable_releaseEb + 268
11 libobjc.A.dylib 0x02405e81 objc_release + 49
12 libobjc.A.dylib 0x02406ce7 _ZN12_GLOBAL__N_119AutoreleasePoolPage3popEPv + 537
13 CoreFoundation 0x02617878 _CFAutoreleasePoolPop + 24
14 CoreFoundation 0x0261c5d3 __CFRunLoopRun + 1971
15 CoreFoundation 0x0261b9d3 CFRunLoopRunSpecific + 467
16 CoreFoundation 0x0261b7eb CFRunLoopRunInMode + 123
17 GraphicsServices 0x036f85ee GSEventRunModal + 192
18 GraphicsServices 0x036f842b GSEventRun + 104
19 UIKit 0x010b5f9b UIApplicationMain + 1225
20 Rally 0x00006a6d main + 141
21 libdyld.dylib 0x02ef6701 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
I've double-checked (ctrl+f) that nowhere else are these methods called. So it seems that for any instance, there is precisely one addObserver
(with unique context) and precisely one removeObserver
(with that context)
Apologies all
Have just spotted my typo:
[self removeObserver:self
forKeyPath:@"currentLocation"
context:MyClassKVOContext];
should be
[[RA_LocationSingleton locationSingleton] removeObserver:self
forKeyPath:@"currentLocation"
context:MyClassKVOContext];