0

I have an UIViewController object. I would like to know when the viewDidLoad method has been called.

I understand that I can override this method in the subclass and find out when it is called.

Is there another to know when the viewDidLoad method is called?

Edit-

I have several view controllers that are pushed onto an UINavigationController. Some of these view controllers hide the navigation bars. This can be done using the answer given here.

override func viewWillAppear(animated: Bool) {
    self.navigationController?.setNavigationBarHidden(true, animated: animated)
    super.viewWillAppear(animated)
}

override func viewWillDisappear(animated: Bool) {
    self.navigationController?.setNavigationBarHidden(false, animated: animated)
    super.viewWillDisappear(animated)
}

At the present, I have repeated this code in a number of view controllers.

I am trying to remove the repetition of code.

One way to do this would be create a super class that contains this code and have the view controllers that hide the navigation bar subclass this super class. However, some of the view controllers that hide the navigation bar descend from UITableViewController and UICollectionViewController.

I am trying to create a class that will observe when the viewWillAppear(_:) and viewWillDisappear(_:) is called on view controller and then call the method to hide and show navigation bar.

  • 3
    Did you try using [Breakpoints](https://medium.com/yay-its-erica/xcode-debugging-with-breakpoints-for-beginners-5b0d0a39d711)? – Aleksey Potapov Sep 16 '19 at 14:07
  • otherwise, there is a great thread [here on SO](https://stackoverflow.com/q/5562938/1040347) about UIViewController's lifecycle – Aleksey Potapov Sep 16 '19 at 14:08
  • As you've also said, you can override the method, and then use a breakpoint to check when is it called. – papafe Sep 16 '19 at 14:14
  • 1
    Why do you need to know that? Answers might be different then. – Larme Sep 16 '19 at 14:20
  • @AlekseyPotapov Breakpoints cannot be used because this is not used for debugging but rather for performing action when the program is running. –  Sep 17 '19 at 07:02

1 Answers1

0

What you are trying to achieve can be implemented in old faithful Objective-C via Method Swizzling.

Go in your Xcode:

  1. Create a New File -> Objective-C with Filename "Lifecycle" and File Type "Category" and Class "UIViewController"

  2. Xcode will offer to create the Bridging Header file if such does not exist.

  3. Put inside your Bridging Header newly created file: #import "UIViewController+Lifecycle.h"

  4. Your UIViewController+Lifecycle.h should look like this:

#import <UIKit/UIKit.h>

@interface UIViewController (Lifecycle)

+ (void)setViewControllerSwizzlingActive:(BOOL)wantedState;

@end
  1. Your UIViewController+Lifecycle.m should look like this:
#import <objc/runtime.h>
#import "UIViewController+Lifecycle.h"

@implementation UIViewController (Lifecycle)

+ (void)setViewControllerSwizzlingActive:(BOOL)wantedState
{
    static BOOL isWorkaroundActive = NO;
    if (isWorkaroundActive != wantedState)
    {
        [self exchangeViewWillAppearMethod];
        [self exchangeViewWillDisappearMethod];
        isWorkaroundActive = wantedState;
    }
}

+ (void)exchangeViewWillAppearMethod
{
    Method original = class_getInstanceMethod(self, @selector(viewWillAppear:));
    Method fake = class_getInstanceMethod(self, @selector(fakeViewWillAppear:));
    method_exchangeImplementations(original, fake);
}

+ (void)exchangeViewWillDisappearMethod
{
    Method original = class_getInstanceMethod(self, @selector(viewWillDisappear:));
    Method fake = class_getInstanceMethod(self, @selector(fakeViewWillDisappear:));
    method_exchangeImplementations(original, fake);
}

- (void)fakeViewWillAppear:(BOOL *)animated
{
    [self.navigationController setNavigationBarHidden:YES animated:animated];
    return [self fakeViewWillAppear:animated];
}

- (void)fakeViewWillDisappear:(BOOL *)animated
{
    [self.navigationController setNavigationBarHidden:NO animated:animated];
    return [self fakeViewWillDisappear:animated];
}

@end
  1. Then, activate your swizzling, say in AppDelegate's didFinishLaunching method like: ViewController.setViewControllerSwizzlingActive(true)

If you want Swift version - this would be a task for you.

Aleksey Potapov
  • 3,683
  • 5
  • 42
  • 65