IOS Swift how reload viewcontroller when app come from background? - ios

I want when user call app from background to reaload one function from viewcontroller?

Elaborating on nishith's answer:
Add the following code to your view controller you want to refresh
override func viewWillAppear() {
super.viewWillAppear()
......
......
NotificationCenter.default.addObserver(self, selector:#selector(YourViewController.methodToRefresh), name: UIApplication.willEnterForegroundNotification, object: UIApplication.shared)
......
......
}
Always remember to cleanup when the view disappears in:
override func viewWillDisappear(animated: Bool) {
NotificationCenter.default.removeObserver(self)
}

You can register your controller for these notifications and reload your controller accordingly.
UIApplicationDidEnterBackgroundNotification
UIApplicationWillEnterForegroundNotification

Related

iOS viewWillAppear not being called when returning from background, even with UIModalPresentationStyle.FullScreen, in iOS 13+

Why isn't iOS calling viewWillAppear when our application is returning from the background, even when I've set UIModalPresentationStyle.FullScreen?
viewWillAppear is a function that responds to a view controller's state change. Background and foreground states are different; they are done at an app level.
You can still respond app state changes by using notifications:
override func viewDidAppear(_ animated: Bool) {
// ...
NotificationCenter.default.addObserver(self, selector: #selector(didReceiveForegroundNotification), name: UIApplication.willEnterForegroundNotification, object: nil)
}
#objc func didReceiveForegroundNotification() {
// app returned from the background
}
Your view controller will listen to events until it is deallocated or removed as an observer. If you don't want to execute code when the view controller has dissappeared, you can do it on viewDidDisappear:
override func viewDidDisappear(_ animated: Bool) {
// ..
NotificationCenter.default.removeObserver(self)
}

UITabBar Lifecycle's methods are not fired from background start

I've have a UITabBar controller as main controller, with 2 tabs. Each tab is a NavigatorViewController with a UIViewController embedded.
If I open the application from background after a previous cold launch, none of the ViewWillAppear (UITabBarController, UIViewController) is fired.
How can I call the lifecycle of UITabBarChildren when user come from backgroud? (IE: From a notification)
That is not in the life cycle because the state of controllers is not changing during background mode or other application events.
You should observe for applicationWillEnterForegroundNotification
class VC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Listen for application event somewhere early like `ViewDidLoad`
NotificationCenter.default.addObserver(self, selector: #selector(applicationWillEnterForegroundNotification), name: UIApplication.willEnterForegroundNotification, object: nil)
}
// Implement a function that you want to execute when event happen
#objc func applicationWillEnterForegroundNotification() {
// Do anything before application Enter Foreground
}
// Remove observer when the controller is going to remove to prevent further issues
deinit {
NotificationCenter.default.removeObserver(self)
}
}
When application comes from background non viewWillAppear/viewDidAppear is called for any active vc , you need to listen to app delegate like applicationWillEnterForegroundNotification
NotificationCenter.default.addObserver(self, selector: #selector(applicationWillEnterForegroundNotification), name: UIApplication.willEnterForegroundNotification, object: nil)
#objc func applicationWillEnterForegroundNotification(_ notification: NSNotification) {
print("To-Do")
}
You can add an observer to UIApplicationWillEnterForeground in your controllers.
Posted shortly before an app leaves the background state on its way to
becoming the active app.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self,selector: #selector(self.appEnteredFromBackground(_:)),name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
}
#objc func appEnteredFromBackground(_ notification: NSNotification) {
print("From background")
}

Swift - notification observer is called several times

I have viewController and inside in viewDidLoad I have
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showNextQuestions", name: "showNextQuestionsID", object: nil)
In another controller I have
NSNotificationCenter.defaultCenter().postNotificationName("showNextQuestionsID", object: nil)
If I go home from app and launch it again function showNextQuestionID fires two times.
I tried to use
func applicationDidEnterBackground(application: UIApplication) {
NSNotificationCenter.defaultCenter().removeObserver(self, name: "showNextQuestionsID", object: nil)
}
But this doesn't help,
and in viewController
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
How can I fix this ?
You are not removing your notification observer in the right place. You register the observer in your view controller subclass, and you need to remove it in the same class. A logical place is to override the viewWillDisappear method. Place the following code in your view controller subclass:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
Also remove
NSNotificationCenter.defaultCenter().removeObserver(self, name: "showNextQuestionsID", object: nil)
From your AppDelegate. When you supply the 'self' argument in the AppDelegate, it is referring to the AppDelegate class, not your view controller. When you call to remove your notification observer in the view controller sublcass, self is your view controller, which is what you want.
Last, when you call simply removeObserver(self) with no other arguments, it will unregister all the observers for that object. That way you don't have to go through and list each observer by name.
Put your observers in AppDelegate or a singleton, so that you can easily add and remove an observer during application states.
applicationDidEnterBackground and deinit should be ok.
The problem is the way you are trying to remove the observer in applicationDidEnterBackground. You are trying to remove the observer from AppDelegate and you need to remove the observer from your ViewController.
To fix the problem:
1) Listen for UIApplicationDidEnterBackgroundNotification in your view controller:
func init() {
super.init()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "myAppDidEnterBackground", name: UIApplicationDidEnterBackgroundNotification, object: nil)
}
2) Implement the method that listen to UIApplicationDidEnterBackgroundNotification
func myAppDidEnterBackground() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: "showNextQuestionsID", object: nil)
}
3) Extra. You could also listen for UIApplicationWillEnterForegroundNotification in order to add again your custom notification

NSNotificationCenter called twice in applicationDidEnterBackground when their is two view controller?

I'm using the the NSNotificationCenter.defaultCenter().postNotificationName function with the applicationDidEnterBackground function. So first I add these to AppDelegate.swift:
func applicationDidEnterBackground(application: UIApplication) {
println("applicationDidEnterBackground")
NSNotificationCenter.defaultCenter().postNotificationName("com.test.mytest", object: self)
}
And I add these to ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "myTestFunc", name: "com.test.mytest", object: nil)
}
func myTestFunc () {
println("CALLED")
}
And up to now, everything is working fine, the console print out the right thing when I enter background:
applicationDidEnterBackground
CALLED
But after I add a new view controller in Storyboard and connect both of them using any of Segue:
And now when I run the app, after I clicked two buttons and then back to the home page, the applicationDidEnterBackground is still calling once but the NSNotificationCenter is called twice:
applicationDidEnterBackground
CALLED
CALLED
So how can I solve this weird problem?
EDIT
I've also tried this, but still same result:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().removeObserver(self, name: "com.test.mytest", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "myTestFunc", name: "com.test.mytest", object: nil)
}
Ah, I forget the viewDidLoad is loaded twice... I solved by:
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self, name: "com.test.mytest", object: nil)
}
I have experienced the same problem. In my case solution was enabling Background Modes in project capabilities tab.

How to update Data in tableview using swift?

Currently I have 3 swift files: ManualViewController, AutoViewController, Main
ManualViewController is the UIViewController with a table view.
AutoViewController is a UIViewController with a few buttons.
Main is just a swift file with all the data for table view.
ManualViewController and AutoViewController are controlled using TabBarController.
When I run the app the initial contents found in Main.swift is loaded onto the table view. When I go to the next view i.e AutoViewController and click on a button to change data in Main.swift, the data changes. The problem is when I switch back to ManualViewController the table still contains the old data and not the updated one.
I also tried this:
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(false)
self.tableView.reloadData()
}
It still din't work.
You can use NSNotificationCenter for update your tableView from another view.
Your -addObserver: declaration has to be like this in your tableView Controller in viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshTable:", name: "refresh", object: nil)
}
And your function for this addObserver will like:
func refreshTable(notification: NSNotification) {
println("Received Notification")
self.tableView.reloadData()
}
Now you can post notification like this when you navigate to your tableView controller:
NSNotificationCenter.defaultCenter().postNotificationName("refresh", object: nil, userInfo: nil)
Check THIS sample project for more Info.
Hope it will help you.
Under normal circumstances, the way to update data in a UITableView is
self.tableView.reloadData()

Resources