Confusion about applicationDidBecomeActive and applicationWillEnterForeground - ios

I have some confusion about the above two app delegation method: I read this link, and it shows that the applicationWillEnterForeground will gets called before applicationDIdBecomeActive gets called. I am not sure about the before means.
If I have a social app: in my applicationWillEnterForeground function, I will check if the there is a current user session; in my applicationDIdBecomeActive, I will reload the content on timelineViewController: Thus, if there is no current user session, the timeline cannot be shown. Suppose a user enter the app from background with no current user session, the applicationWillEnterForeground will show a login page to indicate that there is no user, however, will the next-get-called applicationDIdBecomeActive return back to timeline which are not supposed to show?
If I don't want to modify code in my other viewcontroller, or check user session in applicationDIdBecomeActive. Is there any code I can add in applicationWillEnterForeground function to prevent applicationDIdBecomeActive function running?
Another question: I notice that for some app like Facebook, if I press the home button, turning it to background, but immediately turn it back to screen, the app doesn't show a lot of changes; however, if I let it stay in background for like an hour, it will "freeze" for a while (looks like it is refreshing) when I turn it back to foreground. How does the delegation method design to realize that? Is the system decides which delegation method(the above two) to call basing on the time that the app stayed in background?
BTW, I am using swift as the main programming language of iOS

You can't prevent applicationDidBecomeActive from getting called.
You could set an instance variable in applicationWillEnterForeground which is read later to determine the flow your application uses.

To refresh or initiate VC your app after certain interval like Facebook you can do as follows:
In applicationDidEnterBackground
let app = UserDefaults.standard
let date = Date()
app.set(date, forKey: "activeDate")
In applicationWillEnterForeground
let user = UserDefaults.standard
var interval = 0
if let date = user.object(forKey: "activeDate") as? Date {
interval = Int(Date().timeIntervalSince(date)); print ( "AppDeligate: Inactive interval: \(interval)")
}
if interval > 7200 { // 2hr
// Initiate VC OR Refresh data here
}
if you check time interval in applicationDidBecomeActive, then app get initiate or refresh data when yo view notification from swiping down or swipe up for control center. so applicationWillEnterForeground is the best place to do so.

Related

how to tell when the device screen is locked or unlocked in swift

Essentially I have a timer in my app and I need it to keep running if the phone or device gets locked while the timer is active. After a whole lot of searching I found that's not really possible, or well it is, but doing so could violate apple developer guidelines and could get the app removed from the store.
So I thought I would get a little clever and create a property in my AppDelegate of Int64 for "timerStartedAt" which is just a Date().millisecondsSince1970 (custom extension I have)...
extension Date {
var millisecondsSince1970: Int64 {
return Int64((self.timeIntervalSince1970 * 1000.0).rounded())
}
init(milliseconds: Int64) {
self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1000)
}
}
Then in the "viewWillAppear" of my timer view controller I check that property and set the time has been running of now - that time. However, viewWillAppear doesn't get called when the screen is unlocked. It does get called if the user switches pages in the application, but not when the screen locks and then unlocks.
So I am trying to find a way to call a method in my view controller when the device gets unlocked. Is that even possible?
As the device is being locked, if your app was frontmost, then you'll get applicationWillResignActive(_:) in the app delegate, and the corresponding notification if you register for it.
As the device is being unlocked, if your app was frontmost, then it will be active and frontmost again and you'll get applicationDidBecomeActive in the app delegate, and the corresponding notification if you register for it.
(If your app was not frontmost, you have no way to detect that anything is happening, but that's okay because there is no "you" — the app is not running.)
That is sufficient to let you write a timer that "keeps counting" in the background by looking at the different between the time it started (or the time we deactivated) and the time when we are activated. So the timer effectively "runs" in the background.

how do I pause my app when the user exits, and resume it when they reenter the app?

I want my app to have the ability to run my pause function when the user clicks home. When I exit the app, it pauses, but then runs the view did load function when I enter the app again. Does anyone know how to have the view did load function only run the first time the view loads before it is termitated?
Here is my pause function:
func pauseGame322() {
ThreeTime = 3
CountdownUntillGameLabel.text = String(ThreeTime)
if PlayButton.isHidden == true &&
ContinueButton.isHidden == true{
timer.invalidate()
timer10.invalidate()
TotalSecondsForPause.isHidden = false
PauseView.isHidden = false
UnpauseButton.isHidden = false
TotalSecondsForPause.text = String(time)
}
}
Call your pause function from applicationWillResignActive(_:) in the App Delegate (emphasis mine):
You should use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. An app in the inactive state should do minimal work while it waits to transition to either the active or background state.
If you need access to the current view controller, follow this question. But updating the UI here is pointless. Your app is about to enter the background, the users won't see any UI changes. You display the pause menu when the user comes back, in applicationWillBecomeActive(_:).
You cannot limit the call of viewDidLoad. Every time the ViewController will be initialised, viewDidLoad will be called. To handle such scenario, what you can do is, put your code in a separate method, and call that method from viewDidLoad after performing the check for first time. To know that this is the first time or not, you can simply put a flag variable in UserDefaults.
Further, when you say 'User Exists', it may have different meanings. Did you mean that user kills the app, or you mean that user puts the app in background? For the first case, you should put the check for first time in applicationDidFinishLaunching method, while for the second case (i.e. background), call the pause function from applicationWillEnterBackground, and play from applicationDidEnterForeground.
Try using the application's life cycle methods in more efficient way.

how to give to activity alert in iOS swift?

Suppose App is in foreground and user does not interact with app for 5 min, App should give alert.
Suppose App is in background and it remain in background for more than 5 min App should give alert as soon as app comes in foreground.
Is there any standard way to do that?
For the background part, basically you want to have a Counter. This Counter should do
Observe UIApplicationWillResignActiveNotification notification. And record the time when the selector is called. Let's say it's lastActiveTime.
Observe UIApplicationDidBecomeActiveNotification notification. And inside the selector, compare the current time with lastActiveTime. If it's more than 5 minutes, you'll pop up the alert.
For foreground, you could use some assumptions such as if the top most view controller is the same, assume the user hasn't interacted with the app. You can have a timer that keep checking the top most view controller.

How to show alert when the app is being closed in ios

When my app is running in foreground, If user clicks on home button i want to show some alert like
Do u want to exit the app with Yes/No buttons. Is there any delegate methods called when home button is clicked…
Thank you….
There is no way to do this on iOS. I think you want a similar behavior to Android back button.
Think of iOS home button as Android home button, which doesn't let you prompt user either.
You can not stop the app to go to background, even if you show the alert message, it will go to the background anyways when you hit the home button and you won't see the alert message either.
There is no delegate method that would trigger when the app is going to the background, but there is a delegate method that will trigger when your app has totally gone to background.
Just to show you visually-
In the AppDelegate implementation file(.m), I added an alert message at the end of applicationDidEnterBackground method and put a break point just to check if it is entering that block as I expected. See the result--
You can use these methods in AppDelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

Refresh current view iOS

I found lots of "reloadData" for TableView questions here, but my case is different.
I have a notification App, that uses UILocalNotification to fire reminders.
I need to refresh my tableview in real time after an alert fires, without the need of closing and opening the app to do so...
Example:
User is viewing the scheduled reminders (tableView), when suddenly one of the reminders fires. At this moment, the tableView will reload, but only if the user quits application or go back to another view and open the tableView again. That can't happen cause the application breaks if the user press the row in the tableView witch showed the current reminder (that's already completed and doesn't exists anymore).
I need to reload tableView in real time, without leaving the tableView Controller view. any idea on how to do that?
When a local notification for your app fires while the app is in the foreground, the system sends the application:didReceiveLocalNotification: message to your app delegate. From there, you should notify the view controller (via a direct reference and message send or possibly with a custom NSNotification) to do whatever it needs to do in this case.

Resources