0

I need that instance of my class observe property of itself, so I set observing:

[self addObserver:self forKeyPath:@"myProperty" options:NSKeyValueObservingOptionNew context:nil]

And in dealloc simply check and remove observer:

- (void)dealloc
{
    if ([self observationInfo])
    {
        [self removeObserver:self];
    }
}

This project is under ARC and all work fine prior to iOS 6 SDK. But with iOS 6 SDK, getting observationInfo increase retainCount of object and app crashes after dealloc with EX_BAD_ACCESS (release message sent to deallocated instance).

What is wrong in this code? Is it Apple`s BUG or mine?

UPDATE There is stacktrace:

thread #1: tid = 0x1f03, 0x016b60ab libobjc.A.dylib`objc_release + 27, stop reason = EXC_BAD_ACCESS (code=1, address=0xff000002)

frame #0: 0x016b60ab libobjc.A.dylib`objc_release + 27
frame #1: 0x016b6bd9 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 555
frame #2: 0x02538468 CoreFoundation`_CFAutoreleasePoolPop + 24
frame #3: 0x0253cafd CoreFoundation`__CFRunLoopRun + 1933
frame #4: 0x0253bf44 CoreFoundation`CFRunLoopRunSpecific + 276
frame #5: 0x0253be1b CoreFoundation`CFRunLoopRunInMode + 123
frame #6: 0x024f07e3 GraphicsServices`GSEventRunModal + 88
frame #7: 0x024f0668 GraphicsServices`GSEventRun + 104
frame #8: 0x0022e65c UIKit`UIApplicationMain + 1211
frame #9: 0x00001efd MyProjects`main + 141 at main.m:16
Killer
  • 9
  • 3
  • Not enough info to go on. First, `retainCount` is useless, not helping. Secondly, if you have a crash, post the backtrace. – bbum Dec 10 '12 at 06:24
  • I add stacktrace, it is only autorelease pool cleaning. My opinion is that problem in getting observationInfo. Each calling [self observationInfo] change self.retainCount (increase it, only in iOS 6 SDK). I think that it is very strange behavior, without this checking all works fine. – Killer Dec 10 '12 at 06:44
  • Is there a reason you are observing a property instead of simply overriding the setter? – jrturton Dec 10 '12 at 07:05
  • There is many workarounds to solve this problem, but why this problem can be? – Killer Dec 10 '12 at 07:19

2 Answers2

7

When you call [self observationInfo], it's retaining and autoreleasing self. But since you're already in dealloc, the object will be deallocated before the autorelease pool is drained. So when the autorelease pool is eventually drained, it tries to release your now-deallocated object and crashes. You can see this in the stack trace. Frame #2 is a call to CFAutoreleasePoolPop, which is a function that drains the autorelease pool.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
1

-observationInfo is not designed for this. If you really need to know if you set up KVO or not, store some sort of flag as an instance variable

Mike Abdullah
  • 14,933
  • 2
  • 50
  • 75