Search code examples
iosios5memoryuiviewcontrollercrash

Low memory warning causes a crash on iOS5 - unloadViewForced


I have been able to replicate a low-memory crash on iOS devices that are running iOS5. Every time the stack trace points to the same place, so I know exactly where the problem is. Unfortunately I don't know how to fix it. As you can see below, the crash occurs when CatViewController receives a memory warning. At that point its view gets forcibly unloaded, then the crash happens:

0   libobjc.A.dylib                 0x37174f7e objc_msgSend + 22
1   UIKit                           0x317eab66 -[UIViewController unloadViewForced:] + 130
2   UIKit                           0x31932492 -[UIViewController purgeMemoryForReason:] + 58
3   MyApp                       0x001353c0 -[CatViewController didReceiveMemoryWarning] (CatViewController.m:89)
4   Foundation                      0x339e34f8 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 12
5   CoreFoundation                  0x35178540 ___CFXNotificationPost_block_invoke_0 + 64
6   CoreFoundation                  0x35104090 _CFXNotificationPost + 1400
7   Foundation                      0x339573e4 -[NSNotificationCenter postNotificationName:object:userInfo:] + 60
8   Foundation                      0x33958c14 -[NSNotificationCenter postNotificationName:object:] + 24
9   UIKit                           0x318fd26a -[UIApplication _performMemoryWarning] + 74
10  UIKit                           0x318fd364 -[UIApplication _receivedMemoryNotification] + 168
11  libdispatch.dylib               0x37ae6252 _dispatch_source_invoke + 510
12  libdispatch.dylib               0x37ae3b1e _dispatch_queue_invoke$VARIANT$up + 42
13  libdispatch.dylib               0x37ae3e64 _dispatch_main_queue_callback_4CF$VARIANT$up + 152
14  CoreFoundation                  0x3517f2a6 __CFRunLoopRun + 1262
15  CoreFoundation                  0x3510249e CFRunLoopRunSpecific + 294
16  CoreFoundation                  0x35102366 CFRunLoopRunInMode + 98
17  GraphicsServices                0x3476d432 GSEventRunModal + 130
18  UIKit                           0x31779e76 UIApplicationMain + 1074
19  MyApp                       0x00087142 main (main.m:16)
20  MyApp                       0x000870c8 start + 32

So I believe this has something to do with the way the view is getting unloaded on iOS5. This view controller is not removing itself from any notifications, so this solution doesn't work. Line 89 of CatViewController is just this:

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; //this is line 89
}

And viewDidUnload just looks like this:

- (void)viewDidUnload {
    [self setBackgroundView:nil];
    [self setContentView:nil];
    [self setSomeScrollView:nil];
    [super viewDidUnload];
}

Any ideas on how I can handle this gracefully without crashing?

EDIT: Here's more info on another crash report:

0   CoreFoundation                  0x351ac88f __exceptionPreprocess + 163
1   libobjc.A.dylib                 0x3717a259 objc_exception_throw + 33
2   CoreFoundation                  0x351afa9b -[NSObject doesNotRecognizeSelector:] + 175
3   CoreFoundation                  0x351ae915 ___forwarding___ + 301
4   CoreFoundation                  0x35109650 _CF_forwarding_prep_0 + 48
5   UIKit                           0x317eabdf -[UIViewController unloadViewForced:] + 251
6   UIKit                           0x31932499 -[UIViewController purgeMemoryForReason:] + 65
7   MyApp                       0x000d541b -[CatViewController didReceiveMemoryWarning] (CatViewController.m:96)

Solution

  • Your app is not crashing because it is out of memory. In your crash report, you can see that the exception thrown was actually [NSObject doesNotRecognizeSelector:].

    Firstly, you should move those set to nil statements to didReceiveMemoryWarning; this is the preferred method since viewDidUnload is no longer supported in iOS 6.

    Secondly, to find your crash, step through those statements where you set your properties to nil and make sure none of those cause the crash. Note that you will only have methods with those signatures (self set<propertyName>:]) if those variables are declared as properties, not as mere instance variables.