Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging the class name of all UIViewControllers in a project

We have received a HUGE project from outsourcing that we are trying to "repair". There are hundreds of view controllers within the project. Our goal is to easily determine which class we are currently looking at on the device.

Our solution (which didn't work, hence the SO question) follows.

Override the viewDidAppear method of UIViewController via a category with this:

-(void)viewDidAppear:(BOOL)animated
{
    NSLog(@"Current View Class: %@", NSStringFromClass(self.class));
    [self viewDidAppear:animated];
    //Also tried this:
    //[super viewDidAppear:animated];
}

This category would be put in the .pch of the project.

This would require no extra code to be put in the hundreds of View Controllers and be easily turned on and off. It didn't work because, as we've learned now, <meme>one does not simply override an existing method via category</meme>.

What are we missing?!?

like image 607
adamweeks Avatar asked Dec 13 '12 17:12

adamweeks


3 Answers

The answer is to swizzle the methods! Here is what we came up with:

#import "UIViewController+Logging.h"
#import <objc/runtime.h>

@implementation UIViewController (Logging)

-(void)swizzled_viewDidAppear:(BOOL)animated
{
    NSLog(@"Current View Class: %@", NSStringFromClass(self.class));
    [self swizzled_viewDidAppear:animated];
}

+ (void)load
{
    Method original, swizzled;

    original = class_getInstanceMethod(self, @selector(viewDidAppear:));
    swizzled = class_getInstanceMethod(self, @selector(swizzled_viewDidAppear:));

    method_exchangeImplementations(original, swizzled);

}
@end
like image 100
adamweeks Avatar answered Oct 13 '22 22:10

adamweeks


viewWillAppear log

Here is a solution to print the current view controller class name when it appears, in the console:

  • Create a Symbolic Breakpoint in Xcode
  • for Symbol, add -[UIViewController viewWillAppear:]
  • for Action, add a Debugger Command and this expression: expr -- (void) printf("🔘 %s\n", (char *)object_getClassName($arg1))
  • check Automatically continue after evaluating actions.

enter image description here

This has helped me a lot whenever I got lost in the project!

deinit log

You can also add a log to see when your view controllers deinit is called:

  • Create another Symbolic Breakpoint
  • for Symbol, add -[UIViewController dealloc]
  • for Action, add a Debugger Command and this expression: expr -- (void) printf("🗑 %s\n", (char *)object_getClassName($arg1))
  • check Automatically continue after evaluating actions.

enter image description here

This one is very handy to make sure the view controller gets released from memory and also a good indicator for catching the retain cycles.

I don't suggest using swizzling as it might risk your code being less maintainable.

like image 6
Al___ Avatar answered Oct 13 '22 23:10

Al___


Here is solution for this

In your .pch file include this

#define UIViewController MyViewController
#import "MyViewController.h"

Create your new UIViewController sub class as

.h file

#import <UIKit/UIKit.h>

#ifdef UIViewController
#undef UIViewController
#endif
@interface MyViewController : UIViewController

@end
#ifndef UIViewController
#define UIViewController MyViewController
#endif

And .m file

#import "MyViewController.h"

@implementation MyViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"Current View Class: %@", NSStringFromClass(self.class));
}

@end
like image 3
Inder Kumar Rathore Avatar answered Oct 13 '22 22:10

Inder Kumar Rathore