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.
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!
Notification only called the function when observer_ViewController is active
AppDelegate.m
[[NSNotificationCenter defaultCenter] postNotificationName:kNewShipNotifaction object:ship];
observer_ViewController.m
-(void)viewDidLoad{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(newShipCome:) name:kNewShipNotifaction object:nil];
}
- (void)newShipCome:(NSNotification *)notifacation{
[self updateNotifyWithShip:notifacation.object];
}
Notification didn't call the newShipCome:(NSNotification *)notification method when I'm in another viewController. When I switched to the observer_ViewController, the method still didn't get called.
So...how can I get notification update correctly when I'm not in the observer_ViewController ?
remove de-register code form viewWillDisappear it will work
I have a UITabBarController with some tab and in all of them i have:
-(void)viewDidappear:(BOOL)animated{
......
[[NSNotificationCenter defaultCenter] addObserverForName:kNotificationName object:nil queue: nil, usingBlock{...}
}
and
-(void)viewDidDisappear:(BOOL)animated{
......
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
In another class i post the notification with name kNotificationName:
[[NSNotificationCenter defaultCenter] postNotification:kNotificationName object:nil];
I've set some log on all of this methods, and the order they are called is correct but...if i switch from First to Second tab (and the notification is posted), the first and the second tab receive the notification (but the viewDidDisappear of the first tab is called!).
If from second tab i go to third tab, the first, second, and third tab receive the notification.
I've tried to use:
[[NSNotificationCenter defaultCenter] removeObserver:self name:postNotification:kNotificationName object:nil];
but the behaviour is the same. All observer are notified.
EDIT1:
As suggest to the other topic i've moved all in viewWillAppear: and viewWillDisappear:, but this haven't have any effect.
I've tried to remove the observer after have received the notification, like this:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserverForName:kDLSyncEngineSyncCompletedNotificationName object:nil queue:nil usingBlock:^(NSNotification *note) {
....
[[NSNotificationCenter defaultCenter] removeObserver:self name:kDLSyncEngineSyncCompletedNotificationName object:nil];
}];
}
But, using this (bad) approach too, the notification is received to the first tab too (i've added this code only on the first tab, to check if after press the second tab, the first tab is receiving again the notification).
EDIT2 - SOLVED - (but what is the difference?)
Instead of using *addObserverForName:object:queue:usingBlock*: I've used *addObserver:selector:name:object:* and in this way all works.
Apple documentation say this for the method with usingBlock:
The block is copied by the notification center and (the copy) held
until the observer registration is removed.
Sure, I've called removeObserver....
Inside the block in the addObserver method -
usingBlock:^(NSNotification *notification){
/*
do something
*/
[[NSNotificationCenter defaultCenter] removeObserver:self];
}];
As you might have already checked this in documentation -
Be sure to invoke removeObserver: or removeObserver:name:object: before notificationObserver or any object specified in addObserver:selector:name:object: is deallocated.
How to use UIApplicationDidBecomeActiveNotification?
Should I declare it in viewDidLoad or viewWillAppear to reload data when coming from background to foreground.
Does UIApplicationDidBecomeActiveNotification gets called only when app comes from background to foreground?
Please help.
Thanks.
Sometimes it is useful to have a listener of UIApplicationDidBecomeActiveNotification when you need to make some action in your view controller on wake up from background (in case you entered to background with this view controller on-screen). In such wake up viewWillAppear will not be triggered!
Example of use:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(someMethod) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)someMethod
{
<YOUR CODE AT WAKE UP FROM BACKGROUND>
}
Of course, you can also implement all you need at your app delegate class life cycle.
You get this notification if your app was interrupted by a phone call or push notification. Generally, if your application is getting active on screen after interruption.
You can register any class, that is loaded in memory by the moment application will become active as observer to this notification.
Use following code in viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(someMethod:)
name:UIApplicationDidBecomeActiveNotification object:nil];
Use someMethod to handle this notification. And don't forget to remove this class as observer in dealloc:
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:nil];
The OP asked about system notifications fired when the app is backgrounded and then foregrounded again. The Notification designed to handle this situation is the UIApplicationDidEnterBackgroundNotification and UIApplicationWillEnterForegroundNotification. If you want a notification that fires for a wider range of situations, such as when you have a system notification, take a phone call, a SMS comes in, or you slide up the control pane, as well as being backgrounded then you will want the UIApplicationWillResignActiveNotification and UIApplicationDidBecomeActiveNotification. It's important to recognize that these are different, since you might only need to react if your app is backgrounded, and not for other scenarios.