2011-08-31 34 views
11

Tôi có một giao thức có tên MyProtocol. MyProtocol có một phương pháp bắt buộc:Làm cho lớp học phù hợp với giao thức với thể loại cho các phương pháp hiện có

- (NSUInteger)length; 

Và một số phương pháp khác.

Bây giờ tôi muốn làm cho lớp NSString phù hợp với MyProtocol với một danh mục. Giống như vậy:

@interface NSString (NSStringWithMyProtocol) <MyProtocol> 
@end 

Trong thể loại này tôi thực hiện tất cả các phương pháp không bao gồm phương pháp 'chiều dài', vì tôi muốn triển khai NSString gốc. Tôi không muốn ghi đè nó trong lớp cụ thể này.

Bây giờ tôi nhận được cảnh báo vì việc triển khai MyProtocol không hoàn chỉnh trong danh mục.

Tôi biết có một vài giải pháp để giải quyết vấn đề này.

  1. Tận dụng phương pháp bắt buộc
  2. Pointer Swizzling
  3. Thêm lớp con đến lớp đó là phù hợp với các giao thức. Sau đó, bỏ qua việc triển khai.

Tôi không muốn sử dụng các tùy chọn này vì chúng dẫn đến thiết kế kém cho phần còn lại của mã của tôi.
Tùy chọn 3 là xấu, vì các lớp con trực tiếp hiện tại sẽ không tuân theo giao thức.

Có ai biết cách loại bỏ cảnh báo mà không triển khai phương thức độ dài không?

LƯU Ý: Lớp, danh mục và giao thức chỉ là ví dụ. Tôi đã gặp phải vấn đề này với các lớp khác mà tôi không thể đăng bài. Cảm ơn

EDIT: Đã thêm tùy chọn thứ ba.

Full Code:

Giao thức:

@protocol MyProtocol <NSObject> 

- (void) myMethod; 
- (NSInteger) length; 

@end 

Phạm trù tiêu đề:

#import <Foundation/Foundation.h> 
#import "MyProtocol.h" 

@interface NSString (MyProtocol) <MyProtocol> 
@end 

Phạm trù thực hiện:

@implementation NSString (MyProtocol) 

- (void)myMethod { 

} 

@end 

Điều này dẫn đến các cảnh báo sau.

Incomplete implementation 

Method in protocol not implemented 

Trong ảnh chụp màn hình này bạn có thể nhìn thấy cảnh báo của tôi: Screen shot

tôi đã cố gắng biên soạn với LLVM GCC 4.2 và 3.0 trình biên dịch của Apple LLVM. Tôi cũng đã biên dịch trên xcode 4.0.2 và Xcode 4.2. Tôi đang sử dụng OS X 10.6.8.

Trả lời

7

Tôi không thể tạo lại vấn đề này. Bạn có thể đăng mã thể hiện nó không? Các biên dịch sau đây không có cảnh báo trên 10.7.

#import <Foundation/Foundation.h> 

@protocol MyProtocol <NSObject> 
- (NSUInteger)length; 
@end 

@interface NSString (NSStringWithMyProtocol) <MyProtocol> 
@end 

int main (int argc, const char * argv[]) { 
    @autoreleasepool { 
    id<MyProtocol> foo = @"foo"; 
    NSLog(@"%@", foo);  
    } 
    return 0; 
} 
+1

Tôi đã thêm mã của mình. Tôi cũng thấy những gì khác nhau. Bạn không xác định việc triển khai cho danh mục. –

+1

Clang rõ ràng là chặt chẽ hơn về điều này hơn gcc. Trong phần lớn các trường hợp, đó là một điều tốt, nhưng trong trường hợp này, tôi tin rằng bạn đã đẩy nó vào cạnh của việc thực hiện hiện tại. Tôi sẽ mở một khiếm khuyết chống lại tiếng kêu. –

+1

Tôi nghĩ tôi sẽ ký tên này là câu trả lời đúng. Lưu ý rằng nó sẽ chỉ hoạt động khi một lớp đã thực hiện tất cả các phương thức được định nghĩa trong giao thức. Việc triển khai danh mục không thể tồn tại với việc triển khai một phần giao thức. –

0

Bạn có thể coi đây là một chút của một hack, và tôi không biết nếu nó thậm chí sẽ làm việc, nhưng làm thế nào về tuyên bố nó như là một tài sản duy nhất đọc

@property (readonly, assign) NSUInteger length; 

và sau đó trong việc thực hiện của bạn thể loại, làm cho nó @dynamic

+1

Whould work for a getter, nhưng không phải cho setter. Không chỉ ra đây chỉ là một ví dụ. Không thể nói về mã sản xuất của tôi. –

+0

@Mats: biến nó thành thuộc tính đọc/ghi rồi – JeremyP

+1

Đúng. Nhưng điều đó sẽ không chỉ giải quyết các phương thức setter/getter. Như đã lưu ý trong bình luận trước đây của tôi, tôi đối phó với các lớp và phương pháp khác. –

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