记录项目中所有 UIViewController 的类名

Posted

技术标签:

【中文标题】记录项目中所有 UIViewController 的类名【英文标题】:Logging the class name of all UIViewControllers in a project 【发布时间】:2012-12-13 17:24:35 【问题描述】:

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

我们的解决方案(没有用,因此出现了 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>不能简单地通过 category/meme 覆盖现有方法>.

我们错过了什么?!?

【问题讨论】:

这段代码有一个无限循环,不是吗?你应该调用 [super viewDidAppear:animated]; @BrunoDomingues 因为这是 UIViewController 上的一个类别,所以调用 super 会调用不存在的 NSObject(UIViewController 的超类)上的 viewDidAppear。 你可以从 UIWindow rootViewController 找到当前可见视图(视图控制器)。 @9dan 那到底会去哪里? 我在这里用 [self viewDidAppear:animated] 试过了;它确实有一个无限循环,并且有超级崩溃。在您的项目中 viewControllers 的 viewDidAppear 做了什么?因为默认情况下它什么都不做。您可以删除行 [self viewDidAppear:animated];它会起作用的。 【参考方案1】:

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

#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

【讨论】:

今天一直在使用它,我们遇到了一个“问题”。如果子类调用 viewDidAppear 但没有调用 [super viewDidAppear],则不会得到日志。 刚刚遇到这个。为了其他人阅读 cmets,所有 UIViewController 子类都必须调用 [super viewDidAppear],所以如果缺少它,那是另一个程序员错误。【参考方案2】:

viewWillAppear日志

下面是打印当前视图控制器类名的解决方案,当它出现在控制台时:

在 Xcode 中创建符号断点 对于符号,添加-[UIViewController viewWillAppear:] 对于Action,添加一个调试器命令和这个表达式: expr -- (void) printf("? %s\n", (char *)object_getClassName($arg1)) 勾选评估动作后自动继续

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

deinit日志

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

创建另一个符号断点 对于符号,添加-[UIViewController dealloc] 对于Action,添加一个调试器命令和这个表达式: expr -- (void) printf("? %s\n", (char *)object_getClassName($arg1)) 勾选评估动作后自动继续

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

【讨论】:

【参考方案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

【讨论】:

刚刚有机会测试这段代码,它也能正常工作。与方法调配相比,这种方法有什么优点/缺点吗? 我的代码正在做的是将超类UIViewController 替换为MyViewController。我现在找不到这两种方法的任何缺点.. 感谢您的解决方案,在接受答案之前仍在等待进一步的信息。 当然 :) 寻找最好的【参考方案4】:

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

【讨论】:

很遗憾没有。它们都是 UIViewController 的简单子类。寻找解决方案的方法。 我知道你有数百个控制器,但是一个好的查找/替换可以很容易地帮助你从一个通用的控制器类继承。这将使这项特定任务变得容易,并有其他好处。【参考方案5】:

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

【讨论】:

寻找一个可以在整个应用程序范围内工作的更简单的解决方案,而不是像问题中描述的那样修改每个类。【参考方案6】:

应用程序是否使用导航控制器来显示视图控制器?如果是这样,您可以使用 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);
    

【讨论】:

【参考方案7】:

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

【讨论】:

以上是关于记录项目中所有 UIViewController 的类名的主要内容,如果未能解决你的问题,请参考以下文章

使用目标 c 后,UiViewController 不会从标签栏项目中快速加载

ios项目记录

使用 UIAppearence 更改 UIViewController 的直接子视图的背景颜色

分析屏幕报告已禁用。 UIViewController 转换不会被记录

UIViewController 内容未显示在情节提要上

UIViewController 双模态展示