Actually the requirement is to reload the data when app comes from background. but it doesn't reload when I come from background. I write the method for reloading data on viewDidLoad.
So, where should I write the code to solve my problem?
Thanks...
As KartikArora is implies above, your viewDidLoad is not called when the app comes from the background to the foreground. So the data is not reloaded.
You could reload the data whenever the view appears instead of when the view is loaded. But then it would reload the data every time the view appears, which you might not want.
You could also have a reload method in your view controller that is called when the app enters foreground triggered via a posted notification.
-(void) viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myMethod:) name: UIApplicationWillEnterForegroundNotification object:nil];
}
-(void)myMethod:(id)not {
// code for save data
}
try this
Try it in App Delegate File it will work
- (void) applicationWillEnterForeground: (UIApplication *) application
{
write your code here
}
Either you do it in the UIApplicationDelegates
- (void)applicationDidBecomeActive:(UIApplication *)application
method, or you subscribe your object to the UIApplicationDidBecomeActiveNotification.
Related
Conditions
Getting a notification (txt message)
or Opening/Closing Notification Center
or Switch to another app, come back
Basically, the app comes back from background for a short period.
Issue
Layout is ok, but some of my properties that I get from CoreData are empty after resuming from Background. This issue is there on pretty much all of my view controllers.
The project
This is an app that has a main tabbar controller, with two navigationcontrollers within the tabs and maybe two levels of viewcontrollers, that have themselves child UIViews (that use some of the informations). The back-end is made of Parse and CoreData.
The weird part
Back from background -> properties are ok on viewWillAppear (Create a backup of the id) -> they are nil seconds after -> I need to manually get them back (from the ID I just stored)
Here is a screenshot, when putting a break point within a function called every 5sec to check the current time (link to bigger) :
What I did
NSCoder implemented for state restoration and every view controllers have a restoration ID, however it doesn't get called when app is becoming active. I don't think NSCoder is the issue here since from the documentation it is used when the OS will kill it on its own, or a force quit from the user.
I tried to manually refresh the content in the appropriate ViewControllers from NSNotificationCenter if the NSManagedObjects are nil, but it is not future-proof, and is never the same logic on each view.
Any thoughts? Thank you!
My AppDelegate :
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(#"Will Resign Active");
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"Entered Background");
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(#"Will enter Foreground");
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[NSNotificationCenter defaultCenter] postNotificationName:#"needsRefresh" object:self userInfo:nil]; // Helpful in some viewcontrollers to save variables that are not nil.
[PF_FBSession.activeSession handleDidBecomeActive];
}
- (void)applicationWillTerminate:(UIApplication *)application
{
NSLog(#"Will Terminate");
}
For those finding this thread, here is the solution I found.
My issue and answer was specific to my project.
I had another controller, the one that takes care of all my database connections, that was listening to applicationDidBecomeActive.
This was calling up a refresh of my data, but also a "cleanup", that was deleting/editing some NSManagedObjects, then saving.
Conclusion : the memory address wasn't the same, the object wasn't considered the same, and therefore was empty on my current page.
I fixed it by stopping cleaning up on each AppDidBecomeActive, but move that logic to AppDidFinishLaunching instead.
Hope that helped!
Method viewDidAppear is not getting called after going from the background back into my iPhone Application.
Does anyone have a solution for this?
I need to call a method every time my MainViewController is shown (even after returning from the background) that will change a label to the new date.
viewDidAppear doesn't seem to be working properly.
Actually it is working properly.
Instead, consider installing a notification handler for UIApplicationDidBecomeActiveNotification or UIApplicationWillEnterForegroundNotification, whichever may be more appropriate for your situation. From there you could do an update of your GUI.
You will have the UIApplicationWillEnterForegroundNotification method in App delegate.Now you need to create the object of the class you want and call the viewwillAppear
this method will be called when the app is in background.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
now for the view will appear code like this
- (void)applicationWillEnterForeground:(UIApplication *)application
{
ViewController *vc = [ViewController alloc]init];//you can use your viewcontroller here
[vc viewDidAppear:YES];// this will call the method.
}
Try using viewWillAppear if you dont mind doing this process before the is actually shown.
Else you can use the method.
- (void)applicationWillEnterForeground:(UIApplication *)application{}
I used to addObserver in viewDidLoad: and removeObserver in dealloc:. Code:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshData)
name:AnyNotification
object:nil];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:AnyNotification
object:nil];
}
But according to some articles said, it's better to addObserver in viewDidAppear: and removeObserver in viewDidDisappear:. Code:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshData)
name:AnyNotification
object:nil];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:AnyNotification
object:nil];
}
So, what's the better way to addObserver/removeObserver?
this depends on your scenario, usually the best approach is to add in viewDidLoad and remove in dealloc and in viewDidUnload (deprecated in iOS 9.0, use dealloc only), but there are some cases when you have same method in different classes like UI effects and want to call only current screen's method using notification, then you will have to add the observer in viewWillAppear and remove it in viewWillDisappear or viewDidAppear/viewDidDisappear
Edit:
A note from comments, thanks #honey.
Though now since iOS 9, you no longer need to care about removing the observer. See Apple release notes: "In OS X 10.11 and iOS 9.0 NSNotificationCenter and NSDistributedNotificationCenter will no longer send notifications to registered observers that may be deallocated..
I would normally put it in -viewDidAppear: and -viewDidDisapear: (or -viewWillAppear: and -viewWillDisappear:) simply because in every case I came across I'm only interested in the notification if the view is actually displayed.
It's probably a premature optimisation (your code for handling the notification could take some time, but might be useless if the view is not displayed), but then it's also no more code - it's the same code just in a different method...
Don't forget NSKeyValueObservingOptionInitial. I use it with viewWillAppear/viewWillDisappear so my UI is always up-do-date, even if I hide that view controller, saving resources because I will not update it until is shown again.
The best approach using NSNotifications is adding the observer when you need to observe for notifications and remove them when you don't need them anymore.
This could be on viewDidLoad:, viewWillAppear:, or when the user taps some button etc.
I will give you a little example:
My app has a tabbar, and in some of the view controllers, I'm displaying some info downloaded from internet (a tweet for example). I also have a class pooling for new data from server each 2 minutes, and as the server had new data, I updated the info on database. I will not use a delegate pattern to listen to DB changes, because I have so many view controllers displaying data, and it will be a very bad design making the delegate an array and looping to pass the data for every view controller. So, in this specific scenario, the best to do is to post a notification telling every VC that new data has come.
If your VC removes the delegate when the view disappears, only the current one will receive the notification and update the displaying contents.
You obviously could update the contents of the other VCs before display, on viewWillAppear: for example, but doing this the VC contents will be updated not only when necessary, but each time you change tabs.
It was only one example, where I tried to show you that for NSNotifications, is difficult to advise you when to add or remove observers when we don't have the entire description of how you app behaviours.
-viewWillAppear: + -viewWillDisappear: is better than -viewDidAppear: + -viewDidDisapear:, because they are always called the same number of times.
How can I ensure my table data function is called only once when app is displayed again (from background start, or launch)?
That is, I want to have my table data refreshed when the user clicks on the application icon, and only once. So the requirement would be:
a) update method in controller called only once after application icon is clicked by user
b) to be valid irrespective of whether the user is (i) starting app for the first time, (ii) coming back from background, (iii) any other means of the user requesting the app come back to the foreground.
The issue I currently have with my implementation is that the data update is being called twice in the case where the app is coming back from background, so I basically want to improve on this. The way I'm doing currently, which is flawed is:
- (void)updateEventData {
// UPDATE CODE HERE
}
- (void)becomeActive:(NSNotification *)notification {
[self updateEventData];
[self.tableView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self updateEventData];
// Auto Refresh Data - Handle Case where App becomes active from background & you want to refresh data
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(becomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
You can implement it in following way:
1) Take one variable in NSUserDefault.
2) Set it's value FALSE when app is launch for the first time.
3) Get the value of NSUserDefault variable in respective view controller. And if it's value if FALSE then call update method.
4) Now, when app become Active, then set the variable value TRUE.
5) Get it's value in respective view controller. And if's value is TRUE then don't call update method.
6) So, update method will be called only once.
Hope it will be helpful to you. May be there is some minor changes.
Let me know in case of any difficulty.
Well what i understand from your question that you only want to update the table data when you start your application by clicking the app icon on the iPhone.Well First understand the execution of the app, the main function is called first and then in your app delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[self postNotification];
[self.window makeKeyAndVisible];
return YES;
}
you can post the notification in this method as its called once.
And more over if you want to do this by your own way in the ViewDidLoad method, then i think you must also remove the observer of notification,i think that may be the reason that its being called twice,because you are not removing notification.
As part of writing this question and reviewing answers I think I've got probably a good solution...
Create an instance variable/property "initialLoad"
Set it to TRUE first thing in viewDidLoad
Then in the becomeActive method do the following:
Code:
- (void)becomeActive:(NSNotification *)notification {
if (!self.initialLoad) {
[self updateEventData];
[self.tableView reloadData];
}
self.initialLoad = false;
}
Seems to work ok...
I'm trying to unload a view controller from view when the iPhone goes to sleep. My app has a stopwatch that has to keep counting when the phone goes to sleep or call comes in or the user closes the app without logging out.
I have all this functionality in place, I'm capturing all start times and stop times and upon re-entering the stopwatch view controller, I calculate the difference. It all works beautifully. When I was doing some additional testing I realised I hadn't catered for the iPhone going into sleep mode.
So all I need to do to make sure my stopwatch is correct bring the user back to the app home screen. I know the following method is called when the app goes to sleep:
-(void)applicationWillResignActive:(UIApplication *)application
How do I unload the stopwatch view controller from my app delegate ?
---- UPDATE ----
kpower, thanks for your feedback. I've implemented the following code:
In my App Delegate:
- (void)applicationWillResignActive:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"AppIsAsleep" object:nil];
}
In my view controller, I have the following:
-(void)viewDidLoad
{
// Add Observer.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(viewDidUnload:) name:#"AppIsAsleep" object:nil];
}
- (void)viewDidUnload {
//Remove the Observer.
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"AppIsAsleep" object:nil];
}
When the phone goes to sleep, it actually closes the app, am I doing something wrong ?
Regards,
Stephen
You can use the Notifications mechanism. It allows you to unload view controller from different place (not the AppDelegate) this case.
For example, in your view controller's viewDidLoad method you add an observer (don't forget to remove it in viewDidUnload) and in applicationWillResignActive: method of AppDelegate you just simply post notification. That's all.
↓ Update here ↓
When you get a notification - you should manage view controller's removing by yourself. And calling viewDidUnload here is not the solution, cause this method is called after view controller was already unloaded and doesn't cause removing.
How to remove? Depends on how the view controller was added (for example, popViewControllerAnimated for UINavigationController). The main idea here is to make object's retain count equal to 0 (as you know this case an object will be destroyed) - so you should sent release message necessary amount of times.