2012-12-13 13 views
8

में सभी UIViewControllers के क्लास नाम को लॉगिंग करना हमें आउटसोर्सिंग से विशाल प्रोजेक्ट प्राप्त हुआ है जिसे हम "मरम्मत" करने का प्रयास कर रहे हैं। परियोजना के भीतर सैकड़ों दृश्य नियंत्रक हैं। हमारा लक्ष्य यह निर्धारित करना है कि वर्तमान में हम कौन सी कक्षा डिवाइस पर देख रहे हैं।प्रोजेक्ट

हमारा समाधान (जो काम नहीं करता है, इसलिए SO सवाल) निम्नानुसार है।

इस के साथ एक वर्ग के माध्यम से UIViewController की viewDidAppear विधि ओवरराइड:

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

इस श्रेणी में .pch परियोजना के में डाल दिया जाएगा।

इसके लिए सैकड़ों व्यू कंट्रोलर में कोई अतिरिक्त कोड नहीं डालना होगा और आसानी से चालू और बंद किया जाना चाहिए। यह वजह से काम नहीं था, क्योंकि हम अब सीखा है, < मेम> एक बस श्रेणी < /मेम के माध्यम से एक मौजूदा विधि पर हावी नहीं होता>।

हम क्या खो रहे हैं?!

+0

इस कोड में एक अनंत लूप है, है ना?आपको [सुपर व्यूडिडएपियर: एनिमेटेड] कॉल करना चाहिए; –

+0

@ ब्रूनोडोमिंग्स क्योंकि यह UIViewController पर एक श्रेणी है, सुपर कॉलिंग एनएसओब्जेक्ट (UIViewController के सुपरक्लास) पर ViewDidAppear को कॉल करेगा जो मौजूद नहीं है। – adamweeks

+0

आप UIWindow rootViewController से वर्तमान दृश्य दृश्य (नियंत्रक देखें) पा सकते हैं। – 9dan

उत्तर

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

आज इसका उपयोग कर रहे थे और एक "गॉचा" है जिसे हम पार कर चुके हैं। अगर उपclass ViewDidAppear को कॉल करता है लेकिन [super viewDidAppear] को कॉल नहीं करता है, तो आपको लॉग नहीं मिलेगा। – adamweeks

+0

बस इस पर आया। किसी और के लिए टिप्पणियां पढ़ने के लिए, सभी UIViewController उप-वर्गों को [सुपर व्यूडिडएपियर] कॉल करना होगा, इसलिए यदि यह गुम है, तो यह एक अलग प्रोग्रामर त्रुटि है। – Shinigami

1

क्या व्यू कंट्रोलर एक सामान्य बेस क्लास साझा करते हैं? यदि ऐसा है तो आप इसे [viewDidAppear:] के बेस क्लास के कार्यान्वयन में डाल सकते हैं। यदि वे एक सामान्य आधार साझा नहीं करते हैं, तो शायद यह एक सार्थक कार्य होगा क्योंकि यह किसी भी तरह से आगे बढ़ रहा है (सामान्य विश्लेषण कोड, आदि)

+0

नहीं। वे सभी UIViewController के बस subclasses हैं। समाधान के लिए swizzling विधि में देख रहे हैं। – adamweeks

+0

मुझे पता है कि आपके पास सैकड़ों नियंत्रक हैं, लेकिन एक अच्छी खोज/प्रतिस्थापन आसानी से आपको एक सामान्य नियंत्रक वर्ग से प्राप्त करने में सहायता कर सकता है। इससे यह विशेष कार्य आसान हो जाएगा, और अन्य लाभ भी होंगे। –

0

आप क्या कर सकते हैं एक आवेदन विस्तृत खोजने के लिए और Xcode से की जगह है, लेकिन यह जरूरी नहीं कि हर मामले प्राप्त नहीं कर सकेंगे (लेकिन न तो होगा दृष्टिकोण है कि आप की कोशिश की)। आप "[सुपर व्यूडिडलोड] की तलाश कर सकते हैं;" और "[सुपर व्यूडिडलोड] के साथ प्रतिस्थापित करें; एनएसएलओजी (@" वर्तमान दृश्य वर्ग:% @ ", एनएसएसटींगफ्रॉम क्लास (self.class));"

+0

प्रश्न में वर्णित प्रत्येक वर्ग को संशोधित करने के बजाय, एक आसान समाधान की तलाश है जो आवेदन व्यापक रूप से काम करेगा। – adamweeks

3

यहाँ शामिल इस

#define UIViewController MyViewController 
#import "MyViewController.h" 

ज फ़ाइल

#import <UIKit/UIKit.h> 

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

@end 
#ifndef UIViewController 
#define UIViewController MyViewController 
#endif 

और के रूप में अपने नए UIViewController उप कक्षा बनाएं इस

अपने .pch फ़ाइल में के लिए समाधान है। एम फ़ाइल

#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

आप विधि swizzling उपयोग कर सकते हैं। यहां एक अच्छी मार्गदर्शिका है: http://nshipster.com/method-swizzling/

+0

देखें, स्वीकार्य उत्तर यही है। – adamweeks

संबंधित मुद्दे