Inicio de session del nombre de class de todos los UIViewControllers en un proyecto

Hemos recibido un GRAN proyecto de outsourcing que estamos tratando de "reparar". Hay cientos de controlleres de vista dentro del proyecto. Nuestro objective es determinar con facilidad qué class estamos actualmente mirando en el dispositivo.

Nuestra solución (que no funcionó, de ahí la pregunta SO) sigue.

Reemplace el método viewDidAppear de UIViewController a través de una categoría con esto:

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

Esta categoría se includeía en el .pch del proyecto.

Esto no requeriría un código adicional para poner en los cientos de controlleres de vista y se puede activar y desactivar fácilmente. No funcionó porque, como hemos aprendido ahora, < meme > no simplemente anula un método existente a través de la categoría < / meme >.

¿Qué estamos perdiendo?

La respuesta es swizzle los methods! Esto es lo que se nos ocurrió:

 #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 

Aquí hay una solución para esto

En su file .pch incluya esto

 #define UIViewController MyViewController #import "MyViewController.h" 

Cree su nueva subclass UIViewController como

file .h

 #import <UIKit/UIKit.h> #ifdef UIViewController #undef UIViewController #endif @interface MyViewController : UIViewController @end #ifndef UIViewController #define UIViewController MyViewController #endif 

Y el file .m

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

¿Los controlleres de vista comparten una class base común? si es así, puede ponerlo allí en la implementación de la class base de [viewDidAppear:]. Si no comparten una base común, entonces tal vez sería una tarea que valga la pena, ya que podría ser útil de todos modos para avanzar (código analítico común, etc.)

Puede search y replace ampliamente una aplicación desde Xcode, pero no necesariamente encontrará todos los casos (pero tampoco los enfoques que probó). Puede search "[super viewDidLoad];" y replace con "[super viewDidLoad]; NSLog (@" Clase de vista actual:% @ ", NSStringFromClass (self.class));"

¿La aplicación usa controlleres de navigation para mostrar los controlleres de vista? Si es así, puede utilizar los methods de NavigationController para informar el controller actual:

  - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { [self reportNewController:viewController]; } - (void) reportNewController:(UIViewController *)viewController { NSString *name = viewController.title; NSLog(@"Name is %@",name); } 

Puedes usar el método swizzling. Aquí hay una buena guía: http://nshipster.com/method-swizzling/