12

我们从外包中收到了一个巨大的项目,我们正试图“修复”。项目中有数百个视图控制器。我们的目标是轻松确定我们当前在设备上查看的类别。

我们的解决方案(不起作用,因此出现了 SO 问题)如下。

通过一个类别覆盖 UIViewController 的 viewDidAppear 方法:

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

此类别将放在项目的.pch中。

这将不需要在数百个视图控制器中放入额外的代码,并且可以轻松地打开和关闭。它不起作用,因为正如我们现在所了解的,< meme >one 不会简单地通过 category< /meme > 覆盖现有方法。

我们缺少什么?!?

4

7 回答 7

14

答案是调配方法!这是我们想出的:

#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
于 2012-12-13T17:52:27.810 回答
5

viewWillAppear日志

这是在控制台中打印当前视图控制器类名称时的解决方案:

  • 在 Xcode 中创建符号断点
  • 对于符号,添加-[UIViewController viewWillAppear:]
  • 对于Action,添加一个 Debugger Command 和这个表达式: expr -- (void) printf(" %s\n", (char *)object_getClassName($arg1))
  • 检查评估操作后自动继续

在此处输入图像描述

每当我在项目中迷失时,这对我有很大帮助!

deinit日志

您还可以添加日志以查看何时deinit调用视图控制器:

  • 创建另一个符号断点
  • 对于符号,添加-[UIViewController dealloc]
  • 对于Action,添加一个 Debugger Command 和这个表达式: expr -- (void) printf(" %s\n", (char *)object_getClassName($arg1))
  • 检查评估操作后自动继续

在此处输入图像描述

这对于确保视图控制器从内存中释放非常方便,同时也是捕捉保留周期的一个很好的指标。

于 2019-08-30T10:15:43.157 回答
3

这是解决方案

在你的 .pch 文件中包括这个

#define UIViewController MyViewController
#import "MyViewController.h"

创建新的 UIViewController 子类为

.h 文件

#import <UIKit/UIKit.h>

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

@end
#ifndef UIViewController
#define UIViewController MyViewController
#endif

和 .m 文件

#import "MyViewController.h"

@implementation MyViewController

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

@end
于 2012-12-13T18:08:38.747 回答
1

视图控制器是否共享一个公共基类?如果是这样,您可以将其放在 [viewDidAppear:] 的基类实现中。如果他们不共享一个共同的基础,那么也许这将是一项有价值的任务,因为它在未来无论如何都可能有用(共同分析代码等)

于 2012-12-13T17:28:04.350 回答
0

您可以从 Xcode 进行应用程序范围的查找和替换,但不一定会找到所有情况(但您尝试的方法也不会)。你可以寻找“[super viewDidLoad];” 并替换为“[super viewDidLoad]; NSLog(@"Current View Class: %@", NSStringFromClass(self.class));"

于 2012-12-13T17:53:37.760 回答
0

应用程序是否使用导航控制器来显示视图控制器?如果是这样,您可以使用 NavigationController 的方法来报告当前控制器:

    - (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);
    }
于 2012-12-13T18:13:12.840 回答
0

您可以使用方法调配。这是一个很好的指南: http: //nshipster.com/method-swizzling/

于 2016-09-29T08:55:18.810 回答