2010-03-18 31 views
7

Có cách nào để cung cấp phương pháp triển khai thực hiện (mang cùng tên chính xác của một phương thức được định nghĩa bởi khung công tác) chỉ khi phương thức chưa được xác định trong hệ thống không? Ví dụ phương pháp [NSSomeClass someMethod:] chỉ tồn tại trong Mac OS X 10.6 và nếu ứng dụng của tôi chạy ở 10.5, tôi sẽ cung cấp định nghĩa của phương thức đó trong danh mục. Nhưng khi ứng dụng chạy ở 10.6, tôi muốn phương thức do OS cung cấp để chạy.Điều chỉnh một phương pháp hệ thống thông qua các loại trong Mục tiêu-C?

Bối cảnh: Tôi đang tạo ứng dụng được nhắm mục tiêu cho cả 10.5 và 10.6. Vấn đề là gần đây tôi đã nhận ra rằng phương pháp +[NSSortDescriptor sortDescriptorWithKey:ascending:] chỉ tồn tại trong 10.6 và mã của tôi đã được rải rác bởi cuộc gọi phương thức đó. Tôi có thể cung cấp một cài đặt mặc định cho nó (kể từ thời điểm này không quá khó để thực hiện nó bản thân mình), nhưng tôi muốn một "bản địa" một được gọi là bất cứ khi nào ứng dụng của tôi chạy trên 10.6. Hơn nữa, nếu tôi gặp phải các vấn đề tương tự trong tương lai (với các phương pháp khó thực hiện hơn), tôi có thể không có khả năng loại bỏ việc thay thế một lớp lót.

Câu hỏi này mơ hồ tương tự như Override a method via ObjC Category and call the default implementation? nhưng sự khác biệt là tôi chỉ muốn triển khai khi hệ thống chưa có.

Cảm ơn.

Trả lời

4

Có, điều này là có thể. Vì bạn đang nhắm mục tiêu 10.5+ Tôi giả sử bạn đang sử dụng thời gian chạy ObjC2, điều này làm cho nó khá đơn giản.

Objective-C Runtime Reference có tất cả các phương pháp bạn cần. Cụ thể, bạn có thể sử dụng class_getClassMethod hoặc class_getInstanceMethod để xem phương thức đã tồn tại chưa, và sau đó class_addMethod ràng buộc thực hiện của bạn với bộ chọn đó nếu lớp chưa có nó.

1

Hoặc, bạn chỉ cần thực hiện tìm và phụ -[NSSortDescriptor initWithKey:ascending:] rồi thêm tuyên bố phát hành thích hợp.

Đó là cồng kềnh hơn để thực hiện nhưng ít dễ vỡ và dễ bị lỗi hơn là thay đổi chính lớp đó. Điều đó đặc biệt đúng nếu bạn chưa từng làm điều đó trước đây. Có thể bạn sẽ dành nhiều thời gian hơn để tăng tốc độ ghi đè lên so với khi bạn chỉ thực hiện việc tìm kiếm.

7

Tôi sẽ biên dịch +[NSSortDescriptor sortDescriptorWithKey:ascending:] trong danh mục thành một gói riêng biệt. Sau đó, ngay từ đầu của chính bạn, hãy kiểm tra xem lớp NSSortDescriptor có phương thức sortDescriptorWithKey:ascending: với respondsToSelector: hay không. Nếu nó không được triển khai (tức là bạn đang chạy trên < 10.6), sau đó tải gói với -[NSBundle loadAndReturnError:].

Bằng cách này, bạn sẽ chạy phương thức do OS cung cấp trên 10.6 và triển khai của bạn trên 10.5.

+4

Phương thức tiếp cận thông minh +1 :) –

+0

Đồng ý. Rất tốt đẹp thực sự. –

0

suy nghĩ về sự thỏa hiệp giữa thay đổi phương thức initWithKey: tăng dần: và thêm phương thức mới khi chạy - chỉ lớp con NSSortDescriptor và thay thế tất cả các cuộc gọi NSSortDescriptor bằng NSMySortDescriptor;

//NSMySortDescriptor.h 
@interface NSMySortDescriptor : NSSortDescriptor { 
} 
- (id)initWithKey:(NSString *)keyPath ascending:(BOOL)ascending 
@end 

//NSMySortDescriptor.m 

@implementation NSMySortDescriptor 
- (id)initWithKey:(NSString *)keyPath ascending:(BOOL)ascending{ 
    // check if super i.e. has initWithKey:ascending: method 
    if([NSSortDescriptor instancesRespondToSelector:@selector(initWithKey:ascending:)]) { 
     [NSSortDescriptor initWithKey:ascending:]; 
    } 
    else{ 
    // your custom realization for Mac OS X 10.5 
    //... 
    } 
} 
@end 
+1

'NSSortDescriptor' sẽ không bao giờ trả lời' + initWithKey: tăng dần: ', bởi vì (theo quy ước) các phương thức lớp không được sử dụng' init' trong tên của chúng. –

+0

Ồ vâng, sai lầm của tôi - đã lấy nó từ mã câu hỏi ban đầu. Chắc chắn [[NSSortDescriptor class] respondsToSelector: @selector (sortDescriptorWithKey: ascending :)]; hoặc Ồ vâng, lỗi của tôi - lấy nó từ mã câu hỏi ban đầu.Chắc chắn [NSSortDescriptor instancesRespondToSelector: @selector (initWithKey: ascending :)]; - cảm ơn; – Vladimir

Các vấn đề liên quan