Newsonic
Newsonic

Reputation: 403

How to get notified when a UIViewController appears?

Is there a way to be notified when for example every window/viewcontroller has called viewDidLoad? Like a viewcontrollers tracker. I don't want to repeat code too much. Thanks

Upvotes: 0

Views: 147

Answers (4)

Lew Winczynski
Lew Winczynski

Reputation: 1239

There is another method that doesn't require any overriding of all classes inside of your project to inherit from BaseViewController. That's method swizzling. Method swizzling is the process of changing the implementation of an existing selector at runtime. Basically, it is just changing the functionality of a method at runtime.

So, you can do the following:

extension UIViewController {
    static let classInit: Void = {
        let originalSelector = #selector(viewDidLoad)
        let swizzledSelector = #selector(proj_viewDidLoad)
        swizzling(UIViewController.self, originalSelector, swizzledSelector)
    }()

    // MARK: - Method Swizzling

    @objc func proj_viewDidLoad() {
        self.proj_viewDidLoad()

        let viewControllerName = NSStringFromClass(type(of: self))
        /// Whatever you want in here
        print("viewDidLoad: \(viewControllerName)")
    }
 }

private let swizzling: (AnyClass, Selector, Selector) -> () = { forClass, originalSelector, swizzledSelector in
    guard
        let originalMethod = class_getInstanceMethod(forClass, originalSelector),
        let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector)
    else { return }
    method_exchangeImplementations(originalMethod, swizzledMethod)
}

After that, you need to activate it in AppDelegate this way:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {   
    override init() {
        super.init()
        UIViewController.classInit
    }
    /// ... the rest
}

That's it!

Upvotes: 3

Abu Ul Hassan
Abu Ul Hassan

Reputation: 1396

You may create a BaseViewController and inherit from it every other view controller that you want to observe.

 class BaseViewController:UIViewController{
   func viewDidLoad(){
     super.viewDidLoad()
     print("inherit all viewControllers with this class")
     print("perform your work you wanted to do")
  }
}

class firsViewController: BaseViewController{
   func  viewDidLoad(){
      super.viewDidLoad()
      print("I will call baseViewController too")
  }
}
class SecondViewController: BaseViewController{
    func viewDidLoad(){
      super.viewDidLoad()
      print("I will call baseViewController too")
  }
}

Upvotes: 3

Dhaval Raval
Dhaval Raval

Reputation: 594

You have several ways to do this:

You can create Global class for ex : you have your ViewController class with the code in and then you create subclasses of this instead of UIViewController as concept of inheritance mentioned in another answer.

Or you can also create extension , protocols and class with class methods and you can use that class shared instance to every where you want in view controller.

Upvotes: 1

Mumtaz Hussain
Mumtaz Hussain

Reputation: 1125

Create a base view controller, extend all your controllers with it instead of UIViewController like class MyViewController: BaseViewController {, then you can do anything in the base's viewDidLoad which will run for all controller's having them all do super.viewDidLoad.

Upvotes: 2

Related Questions