Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSNotification leads to segmentation fault

I have a strange behavior with an NSNotification object.
My app has an navigation controller, first view is a table view and the second view is just a view controller which shows data of the selected cell.
So in this data view controller I send a notification when I press a button. The notification also works at first.

BUT when I go back to the table view and push the data view controller on stack again and touch the button with the notification, the whole app crashes with no error log.
Xcode only highlights this line:

[[NSNotificationCenter defaultCenter] 
 postNotificationName:@"toggleNoteView" object:nil];

The function where I send the notification:

- (IBAction) toggleNoteView: (id) sender
{
    [[NSNotificationCenter defaultCenter] 
    postNotificationName:@"toggleNoteView" object:nil];
}

This is the receiver:

- (id)init {
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(toggleNoteView:) 
                                             name:@"toggleNoteView" object:nil];
     ...
}

- (void) toggleNoteView:(NSNotification *)notif  {

    takingNotes = !takingNotes;
}

Edit: Now I did get some error logs.

2011-06-27 23:05:05.957 L3T[3228:707] -[UINavigationItemView toggleNoteView:]: unrecognized selector sent to instance 0x4b235f0
2011-06-27 23:05:06.075 L3T[3228:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationItemView toggleNoteView:]: unrecognized selector sent to instance 0x4b235f0'
*** Call stack at first throw:
(
0   CoreFoundation                      0x3634f64f __exceptionPreprocess + 114
1   libobjc.A.dylib                     0x370a2c5d objc_exception_throw + 24
2   CoreFoundation                      0x363531bf -[NSObject(NSObject) doesNotRecognizeSelector:] + 102
3   CoreFoundation                      0x36352649 ___forwarding___ + 508
4   CoreFoundation                      0x362c9180 _CF_forwarding_prep_0 + 48
5   Foundation                          0x35c45183 _nsnote_callback + 142
6   CoreFoundation                      0x3631e20f __CFXNotificationPost_old + 402
7   CoreFoundation                      0x362b8eeb _CFXNotificationPostNotification + 118
8   Foundation                          0x35c425d3 -[NSNotificationCenter postNotificationName:object:userInfo:] + 70
9   Foundation                          0x35c441c1 -[NSNotificationCenter postNotificationName:object:] + 24
10  L3T                                 0x0003d17f -[Container toggleNoteView:] + 338
11  CoreFoundation                      0x362bf571 -[NSObject(NSObject) performSelector:withObject:withObject:] + 24
like image 641
madmax Avatar asked Jun 27 '11 20:06

madmax


People also ask

What causes segmentation fault 11?

Chances are your system is running out of memory when trying to execute your code, which results in a segmentation fault. This is still valid after 7 years.

What do you mean by segmentation fault?

Overview. A segmentation fault (aka segfault) is a common condition that causes programs to crash; they are often associated with a file named core . Segfaults are caused by a program trying to read or write an illegal memory location.


2 Answers

Don't forget to remove the observer when you unload a view. Basically what's happening is when you post a notification to a non-existing view it can't run the selector, thus crashing your app.

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}
like image 179
sudo rm -rf Avatar answered Oct 19 '22 22:10

sudo rm -rf


From your description, it seems like every time you push a view controller, you're creating a new instance of the view controller to do that.

If that's the case, you need to first make sure you aren't leaking that view controller when you go back to the table view.

Then, in that object's dealloc method, unsubscribe it from the notifications.

-(void)dealloc {
     [[NSNotificationCenter defaultCenter] removeObserver:self];
     //other deallocation code
     [super dealloc];
}
like image 35
executor21 Avatar answered Oct 20 '22 00:10

executor21