2012-12-13 42 views
8

Chúng tôi đã nhận được dự án HUGE từ gia công phần mềm mà chúng tôi đang cố gắng "sửa chữa". Có hàng trăm bộ điều khiển xem trong dự án. Mục tiêu của chúng tôi là dễ dàng xác định lớp mà chúng tôi hiện đang xem trên thiết bị.Ghi tên lớp của tất cả UIViewControllers trong một dự án

Giải pháp của chúng tôi (không hoạt động, do đó câu hỏi SO) sau.

Override phương pháp viewDidAppear của UIViewController qua một thể loại với điều này:

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

Thể loại này sẽ được đưa vào .pch của dự án.

Điều này sẽ không yêu cầu thêm mã để đưa vào hàng trăm bộ điều khiển chế độ xem và dễ dàng bật và tắt. Nó đã không làm việc vì, như chúng ta đã học được bây giờ, < meme> ta không chỉ đơn giản là ghi đè lên một phương pháp hiện qua loại < /meme>.

Chúng ta đang thiếu gì?!?

+0

Mã này có vòng lặp vô hạn phải không?Bạn nên gọi [super viewDidAppear: animated]; –

+0

@BrunoDomingues vì ​​đây là danh mục trên UIViewController, gọi super sẽ gọi viewDidAppear trên NSObject (lớp cha của UIViewController) không tồn tại. – adamweeks

+0

Bạn có thể tìm thấy chế độ xem hiển thị hiện tại (xem bộ điều khiển) từ UIWindow rootViewController. – 9dan

Trả lời

14

Câu trả lời là làm lu mờ các phương pháp! Đây là những gì chúng tôi đã đưa ra:

#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

Được sử dụng ngày hôm nay và có một "hình ảnh" mà chúng tôi đã gặp phải. Nếu lớp con gọi hàm viewDidAppear nhưng không gọi [super viewDidAppear], bạn sẽ không nhận được nhật ký. – adamweeks

+0

Chỉ cần đi qua này. Vì lợi ích của bất kỳ ai đọc nhận xét, tất cả các lớp con UIViewController PHẢI gọi [super viewDidAppear], vì vậy nếu thiếu, đó là lỗi lập trình khác. – Shinigami

1

Bộ điều khiển chế độ xem có chia sẻ một lớp cơ sở chung không? nếu bạn chỉ có thể đặt nó ở đó trong việc thực thi lớp cơ sở của [viewDidAppear:]. Nếu họ không chia sẻ một cơ sở chung, thì có lẽ đó sẽ là một nhiệm vụ đáng giá vì nó có thể hữu ích dù sao đi tới (mã phân tích chung, v.v.)

+0

Thật không may là không. Tất cả chúng chỉ đơn giản là các lớp con của UIViewController. Nhìn vào phương pháp nổi loạn cho giải pháp. – adamweeks

+0

Tôi biết bạn đã có hàng trăm bộ điều khiển, nhưng việc tìm/thay thế tốt có thể dễ dàng giúp bạn kế thừa từ một lớp điều khiển chung. Điều đó sẽ làm cho công việc này trở nên dễ dàng và có những lợi ích khác. –

0

Bạn có thể làm một ứng dụng rộng tìm và thay thế từ Xcode, nhưng nó sẽ không nhất thiết phải tìm mọi trường hợp (nhưng không phải sẽ những phương pháp mà bạn đã cố gắng). Bạn có thể tìm "[super viewDidLoad];" và thay thế bằng "[super viewDidLoad]; NSLog (@" Chế độ xem hiện tại:% @ ", NSStringFromClass (self.class));"

+0

Tìm kiếm một giải pháp đơn giản có thể làm việc rộng hơn, thay vì phải sửa đổi mọi lớp như được mô tả trong câu hỏi. – adamweeks

3

Đây là giải pháp cho điều này

Trong file .pch của bạn bao gồm này

#define UIViewController MyViewController 
#import "MyViewController.h" 

Tạo lớp UIViewController sub mới của bạn như

tập tin .h

#import <UIKit/UIKit.h> 

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

@end 
#ifndef UIViewController 
#define UIViewController MyViewController 
#endif 

Và. m file

#import "MyViewController.h" 

@implementation MyViewController 

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

@end 
+0

Chỉ cần có cơ hội để kiểm tra mã này và nó hoạt động tốt. Liệu phương pháp này có bất kỳ lợi ích/hạn chế nào khi so sánh với phương pháp này không? – adamweeks

+0

Mã của tôi đang làm là nó đang thay thế lớp siêu 'UIViewController' thành' MyViewController'. Tôi không thể tìm thấy bất kỳ hạn chế nào cho cả hai cách tiếp cận ngay bây giờ .. –

+0

Cảm ơn giải pháp của bạn, vẫn đang chờ thêm thông tin trước khi chấp nhận câu trả lời. – adamweeks

0

Ứng dụng có sử dụng Bộ điều khiển điều hướng để hiển thị Bộ điều khiển chế độ xem không? Nếu có, bạn có thể sử dụng các phương pháp của NavigationController để báo cáo trình điều khiển hiện tại:

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