2012-12-13 14 views
8

"修理"しようとしているアウトソーシングからHUGEプロジェクトを受け取りました。プロジェクト内には何百ものビューコントローラがあります。私たちの目標は、デバイス上で現在どのクラスを見ているのかを簡単に判断することです。プロジェクト内のすべてのUIViewControllerのクラス名をログに記録

私たちのソリューション(これはうまくいきませんでした、したがってSOの質問)は次のとおりです。

このカテゴリで経由のUIViewControllerのviewDidAppearメソッドをオーバーライドします

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

このカテゴリには、プロジェクトの.PCHに置かれます。

これにより、何百ものView Controllerに追加したり、簡単にオン/オフすることができます。 > 1は、単にカテゴリ< /ミームを経由して既存のメソッドをオーバーライドしないミーム < 、私たちが今学んできたとして、ので、それは動作しませんでした>。

私たちには何が欠けていますか?

+0

このコードには無限ループがありますか?[super viewDidAppear:animated]を呼び出す必要があります。 –

+0

@BrunoDominguesこれはUIViewControllerのカテゴリなので、superを呼び出すと、存在しないNSObject(UIViewControllerのスーパークラス)でviewDidAppearが呼び出されます。 – adamweeks

+0

UIWindowのrootViewControllerから、現在表示されているビュー(ビューコントローラ)を見つけることができます。 – 9dan

答えて

14

答えは方法をうかがうことです!あなたが広い見つけるとXcodeから交換するアプリケーションを行うことができますが、それは必ずしもすべてのケースを見つけることができません(どちらもあなたがしようとしたアプローチがある)

#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 
+0

今日これを使用していて、私たちが出会った「つかまえ」が1つあります。サブクラスがviewDidAppearを呼び出しても[super viewDidAppear]を呼び出さない場合、ログは取得されません。 – adamweeks

+0

ちょうどこれを見つけました。他の誰かがコメントを読むために、すべてのUIViewControllerサブクラスは[super viewDidAppear]を呼び出さなければなりません。そうでなければ、それは別のプログラマーエラーです。 – Shinigami

1

View Controllerは共通の基本クラスを共有していますか?もしそうなら、それを基底クラスの[viewDidAppear:]の実装に置くことができます。彼らが共通の基盤を共有していない場合、おそらくこれは役に立つと思われる(共通のアナリティクスコードなど)

+0

残念ながら。それらはすべてUIViewControllerのサブクラスです。解決策を探し出す方法を調べる。 – adamweeks

+0

私はあなたが何百ものコントローラを持っていることを知っていますが、良いfind/replaceは簡単に共通のコントローラクラスから継承するのに役立ちます。そうすれば、この特別な作業が簡単になり、他の利点もあります。 –

0

:ここでは、思い付いたものです。あなたは "[super viewDidLoad];を探すことができます"[super viewDidLoad]; NSLog(@"現在のビュークラス:%@ "、NSStringFromClass(s​​elf.class));"ここで

+0

質問に記載されているすべてのクラスを変更するのではなく、アプリケーション全体で機能する簡単なソリューションを探してください。 – adamweeks

3

この

ためのソリューションは、あなたの.PCHファイルである

#define UIViewController MyViewController 
#import "MyViewController.h" 

これを含める

.hファイルとして

#import <UIKit/UIKit.h> 

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

@end 
#ifndef UIViewController 
#define UIViewController MyViewController 
#endif 

を新しいのUIViewControllerのサブクラスを作成して。 mファイル

#import "MyViewController.h" 

@implementation MyViewController 

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

@end 
+0

ちょうどこのコードをテストする機会があり、うまく機能します。このメソッドには、メソッドスウィズリングと比較した場合に利点/欠点がありますか? – adamweeks

+0

私のコードは、スーパークラスの 'UIViewController'を' MyViewController'に置き換えています。私は今のアプローチの両方の欠点を見つけることができませんでした。 –

+0

答えを受け入れる前に、あなたの解決策をお寄せいただきありがとうございます。 – adamweeks

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); 
    } 
0

あなたは、メソッドのスウィズリングを使用することができます。素晴らしいガイドがあります: http://nshipster.com/method-swizzling/

+0

これは受け入れられた答えです。 – adamweeks

関連する問題