I am developing a Cocos2d 2.0 game and can't quiet get around on why my App is crashing.
The console output is as following:
2013-02-08 10:52:08.298 AppName[994:15203] cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from [29] to [40].
2013-02-08 10:52:08.299 AppName[994:15203] cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from [40] to [54].
2013-02-08 10:52:08.300 AppName[994:15203] cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from [54] to [73].
(lldb)
The "game scene" loads and crashes immediately. I can see that has to do with CCSpriteBatchNode but I have absolutely no idea on where exactly the code fails. If I add a breakpoint it is not of much use as it will trigger way to many times before reaching the exact moment when it fails.
What does (lldb) mean? Is there a way to have a more explicit stacktrace? I used to work in Java and Eclipse and there was possible to read in English the full stacktrace.. I whish it was as simle using XCode.
You are probably getting one of those nasty EXC_BAD_ACCESS buggers. nope, no exceptions. For example
#try {
// this is caught
// NSMutableArray *ar = [NSMutableArray array];
// [ar addObject:nil];
// this is caught
// NSMutableDictionary *dic = [NSMutableDictionary dictionary] ;
// [dic setObject:#"a" forKey:nil];
// this crashes , no exception
// NSLog("21");
// and this will cause a message sent to a dealloced instance (zombie).
// no exception, just a bad crash.
GEIntEffect *eff = [GEIntEffect intEffectWithString:#"*1.1"
withOrder:geEffectOrderFightMagic
andImpact:geEffectImpactPositive];
[eff release];
NSLog([eff description]);
[[GameSpecs sharedGameSpecs] setupBattlesInitialSpecs];
// with a comment
}
#catch (NSException *e) {
MPLOGERROR(#"*** an exception [%#] occured while writing the game specs, continuing.\n%#\n\n%#",
e.description,
e.callStackSymbols,
e.callStackReturnAddresses);
}
the first two are trapped and the log statement is explicit, spewing me the stack trace in the log. The NSLog("21") ... ooops, forgot the "#" crashes badly. The fourth example, wrongly releasing an object before use ... well u know what that does. I can only suggest you :
check all your warnings (i had one on the bad NSLog)
Profile your app for zombies, using instruments. A message sent to a dealloced object will also crash nasty.
although there is a performance penalty, ie dont overdo it, some strategically placed try/catch blocks can help immensely. Typically, i wrap any 'update' method in Debug, removing the try/catch in Release.
recheck all your warnings :)
best of luck.
ps : here is what the log looks like when i trap an exception. The offsets are not to a 'line of code', symbolicating allows for that. But, typically, i have enough info from the trace to narrow it down to real close. :
-[MPGameSequencer sequenceInitState] : * an exception [* -[__NSArrayM insertObject:atIndex:]: object cannot be nil] occured while writing the game specs, continuing.
(
0 CoreFoundation 0x028de02e __exceptionPreprocess + 206
1 libobjc.A.dylib 0x022bbe7e objc_exception_throw + 44
2 CoreFoundation 0x02891b6a -[__NSArrayM insertObject:atIndex:] + 314
3 CoreFoundation 0x02891a20 -[__NSArrayM addObject:] + 64
4 Battles 0x00221c49 -[MPGameSequencer sequenceInitState] + 809
5 Battles 0x0021e359 -[MPGameSequencer nextFrame:] + 121
6 Battles 0x00067324 -[CCTimer update:] + 308
7 Battles 0x00070444 -[CCScheduler update:] + 772
8 Battles 0x0009dc81 -[CCDirectorIOS drawScene] + 225
9 Battles 0x0009ef44 -[CCDirectorDisplayLink mainLoop:] + 52
10 QuartzCore 0x007c32d2 _ZN2CA7Display11DisplayLink8dispatchEyy + 110
11 QuartzCore 0x007c375f _ZN2CA7Display16TimerDisplayLink8callbackEP16__CFRunLoopTimerPv + 161
12 CoreFoundation 0x0289d376 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
13 CoreFoundation 0x0289ce06 __CFRunLoopDoTimer + 534
14 CoreFoundation 0x02884a82 __CFRunLoopRun + 1810
15 CoreFoundation 0x02883f44 CFRunLoopRunSpecific + 276
16 CoreFoundation 0x02883e1b CFRunLoopRunInMode + 123
17 GraphicsServices 0x035e57e3 GSEventRunModal + 88
18 GraphicsServices 0x035e5668 GSEventRun + 104
19 UIKit 0x00e9165c UIApplicationMain + 1211
20 Battles 0x000c2bce main + 270
21 Battles 0x00002a15 start + 53
)
Related
I have a legacy app which utilizes Apple's example SimplePing. There is a source file SimplePing.m which contains the next method:
- (void)sendPingWithData:(NSData *)data {
id<SimplePingDelegate> strongDelegate;
...
strongDelegate = self.delegate;
if (...) {
[strongDelegate simplePing:self didSendPacket:...];
}
self.nextSequenceNumber += 1; // CRASH
if (self.nextSequenceNumber == 0) {
self.nextSequenceNumberHasWrapped = YES;
}
}
Crashlytics reports dozens of crashes with stack trace:
Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x00000009de3bbeb8
libobjc.A.dylib objc_msgSend + 16
MyApp SimplePing.m line 313 -[SimplePing sendPingWithData:]
Foundation __NSFireTimer + 88
CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 28
CoreFoundation __CFRunLoopDoTimer + 856
CoreFoundation __CFRunLoopDoTimers + 244
CoreFoundation __CFRunLoopRun + 1484
CoreFoundation CFRunLoopRunSpecific + 424
GraphicsServices GSEventRunModal + 100
UIKit UIApplicationMain + 208
MyApp main.swift line 10
libdyld.dylib start + 4
I have not managed to reprodice it yet, and I know a little about this app so far. But I have to begin researching it somehow. I looked through realization of delegates (btw, they are in Swift - if it's relevant), bit did not find anything criminal so far.
As I know, EXC_BAD_ACCESS normally fires when one tries to access deallocated memory. In this concrete case it could mean that [strongDelegate simplePing:self didSendPacket:...] has somehow deallocated self. But as self is a strong reference, it just could not happen at all - am I right?
May you guys drop me some probable scenarios on how could it crash with EXC_BAD_ACCESS on that line? The only my idea is that some memory overwrite have happened.
UPDATE
I was completely wrong with my assumption "But as self is a strong reference ...". self in nether strong, nor weak. It is just unsafe_unretained, as a smart guy explained: https://stackoverflow.com/a/18011581/674548.
I'm facing this exception, and i'm not being able to figure out the problem.
i tried adding exception breakpoint and symbolic breakpoint but it didn't show any more useful data. it's crashing on the main.h return with nothing in the backtrace
this is the exception:
2016-10-20 17:32:58.615 <AppName>[15655:3398242] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull hasColorGlyphsInRange:attributes:]: unrecognized selector sent to instance 0x10b1acfb0'
*** First throw call stack:
(
0 CoreFoundation 0x000000010aeef34b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010f90221e objc_exception_throw + 48
2 CoreFoundation 0x000000010af5ef34 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x000000010ae74c15 ___forwarding___ + 1013
4 CoreFoundation 0x000000010ae74798 _CF_forwarding_prep_0 + 120
5 UIKit 0x000000010d9c66c1 -[UILabel _determineContentsFormat] + 1475
6 UIKit 0x000000010d9c6f9d -[UILabel _evaluateContentsFormat] + 33
7 UIKit 0x000000010d801923 -[UIView(CALayerDelegate) layerWillDraw:] + 65
8 QuartzCore 0x000000010d2c0b26 _ZN2CA5Layer8display_Ev + 146
9 QuartzCore 0x000000010d2b5596 _ZN2CA5Layer17display_if_neededEPNS_11TransactionE + 294
10 QuartzCore 0x000000010d2b5629 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 35
11 QuartzCore 0x000000010d24362c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 280
12 QuartzCore 0x000000010d270713 _ZN2CA11Transaction6commitEv + 475
13 QuartzCore 0x000000010d271083 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 113
14 CoreFoundation 0x000000010ae93e17 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
15 CoreFoundation 0x000000010ae93d87 __CFRunLoopDoObservers + 391
16 CoreFoundation 0x000000010ae78b9e __CFRunLoopRun + 1198
17 CoreFoundation 0x000000010ae78494 CFRunLoopRunSpecific + 420
18 GraphicsServices 0x0000000111c6fa6f GSEventRunModal + 161
19 UIKit 0x000000010d73df34 UIApplicationMain + 159
20 AppName 0x0000000109998c73 main + 1187
21 libdyld.dylib 0x00000001103f368d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
'-[NSNull hasColorGlyphsInRange:attributes:]: unrecognized selector sent to instance 0x10b1acfb0'
This means you've used a NSNull object. From the call stack, maybe a NSNull used as NSString or NSAttributedString. So you need check it before use it.
if (str != [NSNull null]) {
label.text = str
}
are you use this function hasColorGlyphsInRange if you use
try
if ([self respondsToSelector:#selector(hasColorGlyphsInRange:)]) {
//code
}
You need to be able to read and understand error messages.
You are told that someone or something tried to send a message hasColorGlyphsInRange to an instance of NSNull. Even if it is hard to accept because that shouldn't happen, that's the error message and that's what happened.
So you have put an NSNull instance somewhere where you shouldn't have. hasColorGlyphsInRange doesn't seem documented anywhere, so it's something internal to iOS or macOS. But it very much looks like something about text, and there are UILabel methods on the call stack. And there is a layerWillDraw: on the call stack, so it's something trying to draw a UILabel.
UILabels don't get redrawn immediately, but when the system decides to redraw anything. So the most likely thing is that you have set the text of a UILabel to an NSNull object.
And where does the NSNull object come from? Bets are that you are processing JSON and you assume that you are getting a string and don't check for null objects, and that's why you are setting the text of some UILabel to an NSNull instance.
Hey :) So I've been programming an app that I want to have available on the App Store. However, I have already submitted it twice with rejections concerning a crash when the app is played on an iPad (running 7.0.6 and 7.1, for both submits). The app works perfectly fine on my phone and on my mom's iPad, along with all the simulators. I also looked at the crash log (relevant info posted here):
Date/Time: 2014-03-15 14:29:04.504 -0700
OS Version: iOS 7.1 (11D167)
Report Version: 104
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread: 0
Last Exception Backtrace:
0 CoreFoundation 0x182fb6950 __exceptionPreprocess + 132
1 libobjc.A.dylib 0x18f9901fc objc_exception_throw + 60
2 CoreFoundation 0x182ec0c7c -[__NSPlaceholderDictionary initWithObjects:forKeys:count:] + 396
3 CoreFoundation 0x182ec0ac4 +[NSDictionary dictionaryWithObjects:forKeys:count:] + 72
4 Water Balloon 0x1000b0be4 -[WBLogic updateScoreboard:] (WBLogic.m:406)
5 Water Balloon 0x1000b0598 -[WBLogic checkCollision:] (WBLogic.m:341)
6 Water Balloon 0x1000aff10 -[WBLogic update] (WBLogic.m:231)
7 SpriteKit 0x185e47fb0 -[SKView(Private) _update:] + 236
8 SpriteKit 0x185e45ab0 -[SKView renderCallback:] + 876
9 SpriteKit 0x185e43794 __29-[SKView setUpRenderCallback]_block_invoke + 76
10 SpriteKit 0x185e62a90 -[SKDisplayLink _callbackForNextFrame:] + 288
11 QuartzCore 0x185bbccbc CA::Display::DisplayLinkItem::dispatch() + 36
12 QuartzCore 0x185bbcac8 CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 300
13 IOKit 0x183eb7e74 IODispatchCalloutFromCFMessage + 364
14 CoreFoundation 0x182f682e0 __CFMachPortPerform + 192
15 CoreFoundation 0x182f76890 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
16 CoreFoundation 0x182f767f0 __CFRunLoopDoSource1 + 444
17 CoreFoundation 0x182f74a14 __CFRunLoopRun + 1620
18 CoreFoundation 0x182eb56d0 CFRunLoopRunSpecific + 452
19 GraphicsServices 0x188b51c0c GSEventRunModal + 168
20 UIKit 0x185fe6fdc UIApplicationMain + 1156
21 Water Balloon 0x1000b1c38 main (main.m:16)
22 libdyld.dylib 0x18ff83aa0 start + 4
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x000000019007e58c __pthread_kill + 8
1 libsystem_c.dylib 0x0000000190012804 abort + 108
2 libc++abi.dylib 0x000000018f238990 abort_message + 84
3 libc++abi.dylib 0x000000018f255c28 default_terminate_handler() + 296
4 libobjc.A.dylib 0x000000018f9904d0 _objc_terminate() + 124
5 libc++abi.dylib 0x000000018f253164 std::__terminate(void (*)()) + 12
6 libc++abi.dylib 0x000000018f252a7c __cxa_throw + 132
7 libobjc.A.dylib 0x000000018f990314 objc_exception_throw + 340
8 QuartzCore 0x0000000185bbcd7c CA::Display::DisplayLinkItem::dispatch() + 228
9 QuartzCore 0x0000000185bbcac4 CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 296
10 IOKit 0x0000000183eb7e70 IODispatchCalloutFromCFMessage + 360
11 CoreFoundation 0x0000000182f682dc __CFMachPortPerform + 188
12 CoreFoundation 0x0000000182f7688c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
13 CoreFoundation 0x0000000182f767ec __CFRunLoopDoSource1 + 440
14 CoreFoundation 0x0000000182f74a10 __CFRunLoopRun + 1616
15 CoreFoundation 0x0000000182eb56cc CFRunLoopRunSpecific + 448
16 GraphicsServices 0x0000000188b51c08 GSEventRunModal + 164
17 UIKit 0x0000000185fe6fd8 UIApplicationMain + 1152
18 Water Balloon 0x00000001000b1c34 main (main.m:16)
19 libdyld.dylib 0x000000018ff83a9c start + 0
Usually a crash log would be useful in pointing out where the crash occurred, which would lead to why the crash occurred, but line 406 only points to this line in the code:
scorelabel.position = CGPointMake(width/2, height/2 + 150);
the entire method that this line is in is this:
- (void) updateScoreboard:(BOOL) on
{
if(on)
{
int w = scoreboard.size.width;
int h = scoreboard.size.height;
if(score > highScore)
{
highScore = score;
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:highScore] forKey:#"HighScore"];
}
[highScorelabel setText:[NSString stringWithFormat:#"High Score: %i", highScore]];
CGSize defs;
CGSize ss;
CGSize hs;
defs = [#"Score: 1" sizeWithAttributes:#{NSFontAttributeName: [UIFont fontWithName:#"04b_19" size:scorelabel.fontSize]}];
ss = [[scorelabel text] sizeWithAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"04b_19" size:scorelabel.fontSize]}];
hs = [[highScorelabel text] sizeWithAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"04b_19" size:highScorelabel.fontSize]}];
scorelabel.position = CGPointMake(width/2 - w/4 - defs.width/2 + ss.width/2, scoreboard.position.y + h/4);
highScorelabel.position = CGPointMake((scorelabel.position.x - ss.width/2) + hs.width/2, scorelabel.position.y - ss.height/2 - hs.height/2);
}
else
{
scorelabel.position = CGPointMake(width/2, height/2 + 150);
}
[scoreboard setHidden:!on];
[taplabel setHidden:!on];
[highScorelabel setHidden:!on];
}
I have no idea what the problem could be... Please help me find out why the app is causing their iPads to crash.
EDIT In response to the comment, height and width are determined like this:
width = scene.frame.size.width;
height = scene.frame.size.height;
Which is in - (id) init: (SKScene *) s. Also, I just found out that the entire time my app had been running with the logic scene inheriting from NSObject, not SKScene... Could that have had an influence (the app runs the same when I test it).
It is likely that the actual line of code in the symbolicated report is off by some lines. Since above the reported lines you actually do create dictionaries, and the crash is caused by an exception when creating a dictionary, it is likely that the crash happened. there.
So the lines in question are:
defs = [#"Score: 1" sizeWithAttributes:#{NSFontAttributeName: [UIFont fontWithName:#"04b_19" size:scorelabel.fontSize]}];
ss = [[scorelabel text] sizeWithAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"04b_19" size:scorelabel.fontSize]}];
hs = [[highScorelabel text] sizeWithAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"04b_19" size:highScorelabel.fontSize]}];
And the dictionary is always the same:
#{NSFontAttributeName:[UIFont fontWithName:#"04b_19" size:highScorelabel.fontSize]}
So as a first step you should create a local variable for that dictionary and re-use that.
Now the crash is caused when creating the dictionary, since the exception message is missing in the crash report we have to guess here. One option is that you are trying to set a key to a nil value. So when can [UIFont fontWithName:#"04b_19" size:highScorelabel.fontSize] be nil?
The documentation doesn't really say, but I'd assume this can happen if the font with a given name cannot be found. So you should check if the font is really part of the app bundle you submitted to Apple. Then check if the fontName property is set to the correct value that also works on a device. The documentation says:
The fully specified name of the font. This name incorporates both the font family name and the specific style information for the font
This thread may provide an idea what can go wrong in that case: Crash with exception attempt to insert nil object from objects[0]
I am making a program that strips out frames from a movie. This in Simulator of Xcode 5.0 on iOS 7. The number of objects I am trying to put in this array are 447. (Doesn't seem that many).
My program continuously crashes due to a memory leak either due to array size not being large enough?? (no idea if this statement is right) or due to something else. It consistently fails in the for loop only for vidoes whose number of frames are greater than 350. Less frame videos work fine.
Just a hunch could it have anything to do with the fact that I am storing large original frame images into an array? I am not scaling the frame pics down?
CODE:
NSMutableArray* allFrames = [[NSMutableArray alloc] init];
// get each frame
for (int k=0; k< totalFrames; k++)
{
int timeValue = timeValuePerFrame * k;
CMTime frameTime;
frameTime.value = timeValue;
frameTime.timescale = movie.duration.timescale;
frameTime.flags = movie.duration.flags;
frameTime.epoch = movie.duration.epoch;
CMTime gotTime;
CGImageRef myRef = [generator copyCGImageAtTime:frameTime actualTime:&gotTime error:nil];
[allFrames addObject:[UIImage imageWithCGImage:myRef]];
if (gotTime.value != frameTime.value)
NSLog (#"requested %lld got %lld for k %d", frameTime.value, gotTime.value, k);
//cleanup?
CFRelease(myRef);
}
ERROR:
2013-11-03 20:18:24.746 test[42139:a0b] requested 9925 got 9921 for k 397
2013-11-03 20:18:25.122 test[42139:a0b] requested 9950 got 9946 for k 398
everseHD(42046,0xb029b000) malloc: *** mmap(size=8298496) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
2013-11-03 20:10:31.936 ReverseHD[42046:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(
0 CoreFoundation 0x020305e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x01db38b6 objc_exception_throw + 44
2 CoreFoundation 0x01fe2c3c -[__NSArrayM insertObject:atIndex:] + 844
3 CoreFoundation 0x01fe28e0 -[__NSArrayM addObject:] + 64
4 ReverseHD 0x00003131 -[v1ViewController extractImagesFromMovie] + 3089
5 libobjc.A.dylib 0x01dc5874 -[NSObject performSelector:withObject:withObject:] + 77
6 UIKit 0x00b27c8c -[UIApplication sendAction:to:from:forEvent:] + 108
7 UIKit 0x00b27c18 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
8 UIKit 0x00c1f6d9 -[UIControl sendAction:to:forEvent:] + 66
9 UIKit 0x00c1fa9c -[UIControl _sendActionsForEvents:withEvent:] + 577
10 UIKit 0x00c1e815 -[UIControl touchesBegan:withEvent:] + 254
11 UIKit 0x00b64efb -[UIWindow _sendTouchesForEvent:] + 386
12 UIKit 0x00b65d34 -[UIWindow sendEvent:] + 1232
13 UIKit 0x00b39a36 -[UIApplication sendEvent:] + 242
14 UIKit 0x00b23d9f _UIApplicationHandleEventQueue + 11421
15 CoreFoundation 0x01fb98af __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
16 CoreFoundation 0x01fb923b __CFRunLoopDoSources0 + 235
17 CoreFoundation 0x01fd630e __CFRunLoopRun + 910
18 CoreFoundation 0x01fd5b33 CFRunLoopRunSpecific + 467
19 CoreFoundation 0x01fd594b CFRunLoopRunInMode + 123
20 GraphicsServices 0x032239d7 GSEventRunModal + 192
21 GraphicsServices 0x032237fe GSEventRun + 104
22 UIKit 0x00b2694b UIApplicationMain + 1225
23 ReverseHD 0x0000244d main + 141
24 libdyld.dylib 0x02975725 start + 0
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Memory leak ⇒ lots of memory used
Lots of memory used ⇏ memory leak
You are correctly releasing myRef, which you own since it was created with a copy method, so the code you posted doesn't present any leak.
You are just using a lot of memory by trying to store 447 images.
Doesn't seem that many
is not a good evaluation. You should profile the application using Instruments with the Memory Allocation template and check for the size of the array, which is probably filling all the heap.
If you find out that the frames are too big to be stored in the array, you can reduce the size of the generated frame by using the maximumSize property of AVAssetImageGenerator, for instance
generator.maximumSize = CGSizeMake(320, 180);
As stated in the documentation:
The default value is CGSizeZero, which specifies the asset’s unscaled dimensions.
Using MapKit based on iOS6.1, app will random crash (very low occurrence rate) when I try to remove all MKAnnotations then pop out map view controller. From the crash log it seems be an observer issue, anyone who has experienced the similar issue please give me some insight, any idea or discussion will be appreciated. Thanks in advance.
PS:
UIMapView is a singleton in my app, only create once.
2013-08-13 15:11:59.025 CHSP[9129:c07] CRASH: Cannot remove an observer <MKAnnotationContainerView 0xb8e5120> for the key path "title" from <MKUserLocation 0xbab3440> because it is not registered as an observer.
2013-08-13 15:11:59.060 CHSP[9129:c07] Stack Trace: (
0 CoreFoundation 0x028ff02e __exceptionPreprocess + 206
1 libobjc.A.dylib 0x02030e7e objc_exception_throw + 44
2 CoreFoundation 0x028fedeb +[NSException raise:format:] + 139
3 Foundation 0x01a84a89 -[NSObject(NSKeyValueObserverRegistration) _removeObserver:forProperty:] + 790
4 Foundation 0x01a8471d -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] + 105
5 MapKit 0x009194f9 -[MKAnnotationContainerView _unregisterObserverForBubbleAnnotation:] + 116
6 MapKit 0x00919704 -[MKAnnotationContainerView setBubbleAnnotationView:] + 99
7 MapKit 0x0091925d -[MKAnnotationContainerView _removeBubbleWithAnimation:tellDelegate:] + 247
8 MapKit 0x0091b114 -[MKAnnotationContainerView _deselectAnnotationViewWithAnimation:tellDelegate:] + 128
9 MapKit 0x0091b1e1 -[MKAnnotationContainerView _deselectAnnotationView] + 49
10 MapKit 0x0092198e -[MKAnnotationContainerView _removeAnnotationView:updateCollections:] + 395
11 MapKit 0x009217fe -[MKAnnotationContainerView _removeAnnotationView:] + 48
12 MapKit 0x00921490 -[MKAnnotationContainerView removeAnnotation:] + 375
13 MapKit 0x00921538 -[MKAnnotationContainerView removeAnnotations:] + 160
14 MapKit 0x0090f8bd -[MKMapView removeAnnotations:] + 58
15 CHSP 0x00077fd5 -[UPNewMapViewController removeAllAnnotations] + 101
16 CHSP 0x00076640 -[UPNewMapViewController dealloc] + 64
17 UIKit 0x01055480 -[UIViewController release] + 93
18 libobjc.A.dylib 0x020430c3 objc_release + 51
19 libobjc.A.dylib 0x02043bd9 _ZN12_GLOBAL__N_119AutoreleasePoolPage3popEPv + 555
20 CoreFoundation 0x028a1468 _CFAutoreleasePoolPop + 24
21 CoreFoundation 0x028a5afd __CFRunLoopRun + 1933
22 CoreFoundation 0x028a4f44 CFRunLoopRunSpecific + 276
23 CoreFoundation 0x028a4e1b CFRunLoopRunInMode + 123
24 GraphicsServices 0x02c927e3 GSEventRunModal + 88
25 GraphicsServices 0x02c92668 GSEventRun + 104
26 UIKit 0x00f7753c UIApplicationMain + 1211
27 CHSP 0x0009d9a2 main + 130
28 CHSP 0x00002f55 start + 53
)
2013-08-13 15:11:59.061 CHSP[9129:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <MKAnnotationContainerView 0xb8e5120> for the key path "title" from <MKUserLocation 0xbab3440> because it is not registered as an observer.'
Fixed by myself.
Originally I try to use another image to show user current location instead of Mapkit default one, seems it is not a good idea.
I think I found the actual problem.
I can consistently reproduce the issue (even on iOS 5.1) with the following sequence:
1) have your app show annotations + user location
2) press home button to push app to background
3) disable location services and wait until the app is really stopped (I waited 60seconds)
4) go back to app (in my case my app was setup to update as soon as it is started, which will cause it to try to remove old annotations before adding new ones)
=> here the app will crash.
I debugged it by doing my own "removeAnnotations:" method by iterating thru all of them and I found that when it crashed it was trying to remove one more annotation than I had initially added.
The problem did not happen if user location was not shown (either because location services was never enabled, either because other reasons), so I figured it would be a sort of race, because when disabling location services in step 3) above, MKMapView will remove automatically the user location once it found out location services are disabled. However, if the app grabbed the annotations array before, it would still contain the userlocation, which is being released/destroyed in a separate thread by MKMapView, hence the race.
So the answer is that you need to remove only the annotations you added. Here's my code:
- (void)removeAnnotations
{
NSArray *currentAnnotations = [m_MapView annotations];
int count = [[m_MapView annotations] count];
if (currentAnnotations && count)
{
NSMutableArray *annotationsToRemove = [NSMutableArray arrayWithCapacity:count];
for (id annotation in currentAnnotations)
{
if ([annotation isKindOfClass:[MyAnnotation class]])
{
[annotationsToRemove addObject:annotation];
}
}
DBGLOG(#"removeAnnotations: current_count %d, to_be_removed_count %d\n", count, [annotationsToRemove count]);
[m_MapView removeAnnotations:annotationsToRemove];
annotationsToRemove = nil;
}
currentAnnotations = nil;
return;
}