iOS 6.0+: app crashes on resuming, caused by UISearchBar notification zombie

Originator:argentumko
Number:rdar://13539442 Date Originated:30-Mar-2013
Status:Closed Resolved:14-Jul-2013
Product:iPhone SDK Product Version:6.0
Classification:Crash/Hang/Data Loss Reproducible:Always
 
Summary:
If UISearchBar's delegate calls resignFirstResponder in searchBarTextDidBeginEditing, and search bar is then deallocated, app crashes as soon as it's put to background and back to foreground again. The same doesn't happen to UITextField and its corresponding textFieldDidBeginEditing delegate method.

Steps to Reproduce:
1. Given a simple iPhone application: navigation controller (as root for app window), view controller "A", view controller "B". A's view contains a button that, when pressed, creates an instance of "B" and pushes it into navigation controller. B's view contains a search bar and is set to be a delegate of it.
2. "B" as a delegate of its search bar contains method searchBarTextDidBeginEditing, written as follows (only the cause of crash is left for the sake of simplicity; of course this makes this exact search bar unusable):

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
    [searchBar resignFirstResponder];
}

3. User launches this application and is presented with a navigation controller with an instance of view controller A.
4. User presses the button: view controller "B" is pushed into view.
5. User taps on search bar. searchBarTextDidBeginEditing method is called and search bar resigns first responder immediately.
6. User taps "Back" button of navigation controller and "A" is pushed back into view.
7. User hides the app.
8. User opens app back in a few seconds.

Expected Results:
User is presented with the same view of view controller "A".

Actual Results:
App crashes right when it enters foreground.

Regression:
This crash occurs on iOS 6.0 and newer, on both Simulator and real device, at least on iPhone. It doesn't occur on 5.0 and 5.1 Simulators though.

Notes:
An extensive investigation was done here on stackoverflow: http://stackoverflow.com/questions/12601406/ios-app-crashes-on-resuming
Of course, the best workaround would be to avoid resigning first responder in searchBarTextDidBeginEditing and returning NO from searchBarShouldBeginEditing, but it is not documented that client code can't do it the described way, too.
Attached is a crash log from iPhone 4S running iOS 6.1.3, where this crash still happens. It seems that when search bar receives resignFirstResponder in searchBarTextDidBeginEditing, a subscription to a notification called "UIApplicationResumedNotification" (non-documented, private one) with selector _applicationResuming is orphaned and is not removed when search bar deallocates. This notification is posted when app returns to foreground, and in this case app crashes because notification center tries to dispatch the notification to a zombie.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!