0

I have a view controller when a button clicked I'm taking the user to app settings.

 UIApplication.openApplicationSettings()

When I come back from appsettings to app then viewwillappear method is not firing.

or is there any other method that will let us know the appsettings is dismissed and user is seeing the screen right now.

D C T
  • 39
  • 10

2 Answers2

2

You should be using app lifecycle events (SceneDelegate/AppDelegate), not view controller lifecycle events (viewDidLoad, viewDidAppear, etc). sceneDidBecomeActive(_:) should be fine for your purposes — for iOS 13+, you should be using SceneDelegate to listen to scene phases, like going to settings (becoming inactive) and then coming back (becoming active again).

/// SceneDelegate.swift
func sceneDidBecomeActive(_ scene: UIScene) {
    // Called when the scene has moved from an inactive state to an active state.
    // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.

    /// your code here
}

If you want to listen to sceneDidBecomeActive directly in your view controller, try listening to the didActivateNotification notification.

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver( /// add observer
            self,
            selector: #selector(activated),
            name: UIScene.didActivateNotification,
            object: nil
        )
    }
    
    @objc func activated() {
        print("View controller is back now")
    }
}
aheze
  • 24,434
  • 8
  • 68
  • 125
  • May I use sceneDidBecomeActive Directly on viewcontroller or do I have to look for notification ? – D C T Sep 08 '21 at 16:19
  • @DCT yeah, you can use the `didActivateNotification` notification if you want. See my edit – aheze Sep 08 '21 at 16:35
  • Thanks it works.But how do I remove the observer ? – D C T Sep 08 '21 at 16:50
  • @DCT no need, it's automatic. But if you really want to, put it inside `deinit {}`. – aheze Sep 08 '21 at 16:55
  • Could you give example of removing it as well please ? – D C T Sep 08 '21 at 17:12
  • @DCT sure, `deinit { NotificationCenter.default.removeObserver(self, name: UIScene.didActivateNotification, object: nil) }`. But as I said, this is optional. There's no difference whether you use this or not. – aheze Sep 08 '21 at 17:37
  • I'd like to keep one method in both activated() and viewwillappear. Is it possible that activated and viewwillappear can get called sequentially ? – D C T Sep 16 '21 at 17:52
  • @DCT what do you mean? Can you give an example? – aheze Sep 16 '21 at 18:09
  • I mean if I keep a method invocation in both acivate and vewillappear.. I don't want both of them to be called together or one after another – D C T Sep 17 '21 at 17:50
  • @DCT so only call 1 or the other? Maybe set a flag, `var isLoaded = false` directly inside `ViewController`. Then in `viewDidAppear`, call the function if this is false, then set it to true. From then on, only the `activated` function (connected to SceneDelegate) will be called. – aheze Sep 17 '21 at 17:57
0

Subscribe to following appdelegate events

applicationDidBecomeActive 

or

applicationWillEnterForeground

In ViewDidLoad use below code snippet

NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)

and use below method

  @objc func applicationDidBecomeActive(notification: NSNotification) {
        updateTableUI()
    }

Remove observer

   deinit {
           NSNotificationCenter.defaultCenter().removeObserver(self)
   }
CuriousMan
  • 42
  • 11