A UIViewController adds itself to the default center:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(editFood)
name:#"editFood"
object:nil];
Then a UITableView delegate NSObject posts a NSNotification:
[[NSNotificationCenter defaultCenter]
postNotificationName:#"editFood"
object:self];
During run time it get a EXC_BAD_ACCESS exception.
Is the defaultCenter getting released somewhere? The same concept works when I post a notification to a UIViewController from a UIViewController, but that shouldn't matter, right?
One of your subscribers has been deallocated. Make sure to call [[NSNotificationCenter defaultCenter] removeObserver:self] in your dealloc (if not sooner).
EXC_BAD_ACCESS can happen even after verifying dealloc exists like so:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self]
}
The above will solve the problem most of the time, but apparently my cause was that I was indirectly adding the observer with a selector: set to nil as follows:
[NSNotificationCenter.defaultCenter addObserver:self
selector:nil
name:notificationName
object:nil];
...so when I posted something with that notificationName, EXC_BAD_ACCESS occurred.
The solution was to send a selector that actually points to something.
I had the same issue in Swift. The problem was the function target had a closure parameter with default value:
#objc func performFoo(completion: (() -> Void)? = nil) {
...
}
After I replace the closure parameter with a Notification parameter, it worked:
#objc func performFoo(notification: Notification) {
...
}
I had to make some refactor to make it works in a right way.
Related
I have two class which uses NSNotification to communicate with each other.
Currently, i have an issue with notification being fired twice, i've double/triple/even more checked that observer is not added more then 1 time, notification not being posted twice, did global search on my project for same notification.
My code is like below
Added Notification Observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:notification_deleteMediaFromGallery object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notificationReceiver:) name:notification_deleteMediaFromGallery object:nil];
Notification Receiver
- (void)notificationReceiver:(NSNotification*)notification {
if ([notification.name isEqualToString:notification_deleteMediaFromGallery]) {
if ([[notification.userInfo objectForKey:#"kind"] integerValue]==GalleryKindPhoto) {
//My statements
}
else if ([[notification.userInfo objectForKey:#"kind"] integerValue]==GalleryKindVideo) {
//My statements
}
}
}
Post Notification
dispatch_async(dispatch_get_main_queue(), ^{
[_browser reloadData];
[[NSNotificationCenter defaultCenter] postNotificationName:notification_deleteMediaFromGallery object:nil userInfo:#{#"index":#(_browser.currentIndex), #"kind":#(self.kind), #"function":[NSString stringWithFormat:#"%s",__PRETTY_FUNCTION__]}];
});
I have also tried this solution by EmptyStack but not get it to work.
I'll be very thankful to you if you could help me solve this issue.
Thanks.
Edit
NOTE
I've added observer in my viewdidload, and cant add/remove observer from viewwillappera/viewwillappear or viewdidappear/viewdiddisappear because the next viewcontroller which will be pushed on current viewcontroller will post notifications
I think you need to write dealloc method in your view controller. And remove All Notification observer in dealloc method,
- (void)dealloc
{
// Deregister observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:notification_deleteMediaFromGallery object:nil];
}
Hi please make sure your method is not calling two time from where you are firing notification.
& please add your notification observer in viewWillDisappear method.
I am using NSNotification to pass value between ViewControllers, but value is not getting passed and when i used breakpoints to check what's going wrong i came to know that the receive notification selector method is not called.
Following is the code what i have written
AViewController.m
[[NSNotificationCenter defaultCenter] postNotificationName:#"speciality" object:nil userInfo:[specialityIdArray objectAtIndex:indexPath.row]];
BViewCOntroller.m
-(void)viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveSpecialityId:) name:#"speciality" object:nil];
}
-(void)receiveSpecialityId:(NSNotification *)notificaton
{
NSString *selectedServiceString=[[notificaton userInfo] valueForKey:#"service"];
_specialtiyId = selectedServiceString;
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"service" object:nil ];
}
I am trying to pass value from AViewController to BViewController
I have read all the discussions done previously on this same issue, but none of them solved my issue
Dont' add
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveSpecialityId:) name:#"speciality" object:nil];
in the viewDidAppear. I don't know much objective c but here's the deal in swift:
func receiveSpecialityID(notification: NSNotification){
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(<Theclassinwhichthismethodiswritten without the ()).receiveSpecialityID(_:)), name: "Selected", object: nil)
/// DO your thing here..
}
Then do a:
deinit{
NSNotificationCenter.DefaultCenter().removeObserver
}
This should work. Try and let me know!
I have three viewControllers, and I'm trying to send a notification from viewController 3 to viewController 1 and 2. I think the best way to do this is to use NSNotification. Here's what I have so far:
In class C - Post the notification
[[NSNotificationCenter defaultCenter] postNotficationName:#"Updated "object:self];
In class B
In class A and B - Register first for the notification
// viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleUpdate:) name:#"Updated" object:nil];
-(void)handleUpdate:(NSNotification *)notification {
NSLog(#"recieved");
}
This works so far. But when I de-register it in class A and B:
- (void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
The handleUpdate method doesn't get called. So the obvious problem is when I removeObserver's for the notification.
My question is, if everything I did so far is correct, why isn't it working when I remove the removeObserver? If it's not correct, where can I removeObserver's?
Everything you did is right. this is how the notification work.
If your class A,B always need to handle the update, you won't removeObserver.
Because you add your "addObserver" in viewDidLoad. it means you addObserver only once.
The normal error is that you add "addObserver" in "viewWillAppear" or "viewDidAppear", it will add more than once observer in the class. Then, you have to removeObserver in viewDidDisappear.
i try to reload a tableview when the app enter in foreground.
in the ViewController -> viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(updateTableViewData:) name: #"UpdateTableViewAccueil" object:nil];
in the ViewController the method used:
-(void)updateTableViewData:(NSNotification *) notification
{
[self readMsgsFromDB];
[self reloadTableMsgsReceived];
}
in appDelegate.m -> applicationWillEnterForeground
[[NSNotificationCenter defaultCenter] postNotificationName: #"UpdateTableViewAccueil" object: nil];
after i launch the app from xcode, the first time when app enter in foreground the table is reloaded, but not the next times
Do you have some advices? Thanks in advance
I faced a similar issue while trying to reloadData on receiving an NSNotification. It seems the notification is received in a thread different from the main thread. The below code, helped fix it.
Swift:
dispatch_async(dispatch_get_main_queue(), {self.tableView.reloadData()})
Replace
self.tableView.reloadData()
with the code you are using to reload the tableview.
On a side note, you do not have to post a custom notification to capture the fact that the application will enter the foreground. Try swapping this:
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(updateTableViewData:) name: #"UpdateTableViewAccueil" object:nil];
With this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateTableViewData) name:UIApplicationDidBecomeActiveNotification object:nil];
If that works, you can remove the post notification you have.
Hi i am trying to use NSNotification center in my application.The selector method is not being called from the code.I found similar questions in this site like this, but still i am unable to resolve the error.
i am posting notification in appdelegate did finish launching as:
[[NSNotificationCenter defaultCenter] postNotificationName:#"ualert" object:self userInfo:userDict];
adding an observer in one of the view controller as:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(remoteNotificationReceived:)
name:#"ualert"
object:nil];
my selector method is:
- (void)remoteNotificationReceived:(NSNotification *)notification
{
NSLog(#"Notification: %#", notification.userInfo);
}
removing observer as:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
You are posting ualert in applicationDidFinishLaunching which will necessarily occur before your view controller is loaded (and therefore before you have added the observer for the notification).