2011-12-05 18 views
12

Tôi cần trợ giúp gỡ lỗi lớp học của mình. Tôi nhận được một lỗi rất kỳ lạ mà tôi không thể tìm thấy bất cứ điều gì tương tự, vì vậy tôi chỉ sẽ đặt xuống hầu hết các mã của tôi.Lỗi Xcode: Không có phương pháp thể hiện đã biết nào cho bộ chọn

//Tab.h 
#import <UIKit/UIKit.h> 
@class Tab; 
@protocol TabDelegateDataSource <NSObject> 
@required 
-(void)removeTab:(Tab *)tab; 
@end 

@interface Tab : UIView 
{ 
    id <TabDelegateDataSource> __strong _delegate; 
} 

@property(strong) id <TabDelegateDataSource> delegate; 

-(void)removeTab; 

@end 

// Tab.m 
#import "Tab.h" 
@implementation Tab 
@synthesize delegate = _delegate; 
-(void)removeTab 
{ 
    [self.delegate removeTab:self];//Error here saying: No known instance method for selector 'removeTab:' 
} 

@end 
+1

Ra khỏi tò mò, những gì sẽ xảy ra nếu bạn thay thế 'self.delegate' bằng' _delegate' trên dòng vi phạm? – dasblinkenlight

+0

Đại biểu của bạn có thực sự có phương thức 'removeTab' không? Thông báo lỗi này là ngụ ý nó không. Hãy thử gỡ lỗi và kiểm tra self.delegate, và chắc chắn rằng nó là những gì bạn mong đợi, và rằng nó có một phương pháp 'removeTab'. – WilHall

+1

sự cố không nằm trong mã bạn đã đăng. Tôi đã sao chép nó vào một dự án mới và nó biên dịch mà không có lỗi và cảnh báo –

Trả lời

5

Tôi nghĩ rằng đó là một vấn đề ngu ngốc với Xcode tôi khởi động lại ứng dụng một vài lần và nó đã kết thúc làm việc.

+0

Tôi không thể tin rằng câu trả lời này hoạt động nhưng khởi động lại Xcode đã giải quyết được vấn đề của tôi. Cảm ơn bạn. – PhatHV

4

Bạn nên thường xuyên kiểm tra đại biểu của mình theo cách này, trước khi gọi một phương pháp, thậm chí với các phương pháp giao thức yêu cầu:

if(self.delegate != nil && [ self.delegate respondsToSelector: @selector(removeTab:) ] 
{ 
    /* Call delegate method... */ 
} 

Làm như vậy ngay cả đối với các phương pháp cần bổ sung thêm an toàn, như việc kiểm tra này là được thực hiện khi chạy.
Ai đó có thể bỏ qua hoặc vô hiệu hoá cảnh báo trình biên dịch hoặc đánh lừa trình biên dịch bằng loại phôi.

Ví dụ:

UILabel * label  = [ [ UILabel alloc ] initWithFrame: CGRectZero ]; 
someTableView.delegate = (id <UITableViewDelegate>)label; 

Ngoài ra, bạn có thể muốn sử dụng performSelector cho cuộc gọi phương pháp thực tế:

[ self.delegate performSelector: @selector(removeTab:) withObject: self ]; 
+6

Tôi không thấy lý do tại sao điều này cần thiết cho các phương thức được định nghĩa theo yêu cầu trong giao thức. Trình biên dịch sẽ hiển thị cảnh báo nếu phương thức được yêu cầu không được triển khai. –

+1

@Macmade Điều gì là hợp lý để thích 'performSelector' hơn một cuộc gọi phương thức? – zaph

+0

@fluchtpunkt Đây là một sự an toàn bổ sung, vì vậy bạn không dựa vào cài đặt trình biên dịch. Xem chỉnh sửa của tôi, giải thích lý do kiểm tra thời gian chạy. – Macmade

1

Cố gắng đổi tên delegate cho người khác như delegateForTab.

lớp học của bạn Tab được subclassing UIView, vì vậy self.delegate 's self lớp cũng là một lớp con của UIView. UIView có thể có đại biểu riêng của mình (nó được kế thừa từ UIResponder và sâu từ NSObject), và nó không có phương thức -(void)removeTab. Chỉ cần đoán cá nhân của tôi.
Giải pháp của tôi là đổi tên nó (không tìm thấy câu trả lời cho dù nó có thể được phân lớp chưa).

Đề xuất cho sử dụng đại biểu: Bạn nên thực hiện các và sử dụng delegate trong bộ điều khiển xem khác, không phải trong lớp học tương tự mà bạn khai báo nó. :)

+0

Thực hành tốt, nhưng UIView không có đại biểu. Vì vậy, điều này sẽ không giúp đỡ không may ...:) – Macmade

+0

@Macmade, cảm ơn lời khuyên của bạn!Tôi đã gặp vấn đề này trước đây: Tôi tạo ra một lớp kế thừa từ UINavigationController, dẫn đến lỗi tương tự, và tôi đã giải quyết nó bằng cách đổi tên 'delegate'. Chỉ cần bây giờ, tôi tham khảo SDK, UIView không có đại biểu của nó, nó là đúng. :) Tuy nhiên, nó kế thừa từ 'UIResponder' và sâu từ' NSObject'. 'NSObject' có giao thức & đại biểu của nó. Vì vậy, tôi nghĩ rằng '[self.delegate removeTab: self];' '' self' chỉ là một NSObject. Tôi không chắc đây có phải là lý do thực sự hay không. Chỉ cần đoán cá nhân của tôi. : p – Kjuly

0

Lỗi này không phải là lỗi trình biên dịch phải không? Bởi vì tôi không có lỗi trình biên dịch với mã của bạn ở đây.

Vì vậy, nếu đây là một lỗi thời gian chạy, có bạn tuyên bố <TabDelegateDataSource> trong các lớp đại biểu của mình như thế này:

@interface SomeClass : UIView <TabDelegateDataSource>

Nếu bạn đã làm như vậy, trình biên dịch nên được cảnh báo bạn nếu phương pháp dụ của bạn có thể không được tìm thấy.

Hoặc có thể bạn cũng nên đăng mã của lớp đại biểu để biết thêm thông tin.

P.S. Đại biểu không được là __strong. Thay vào đó, bạn nên sử dụng __unsafe_unretained.

14

Tôi hiện có thể tạo và sửa lỗi này theo ý muốn.

Hãy chắc chắn rằng tiêu đề .h nơi này được định nghĩa ...

@protocol TabDelegateDataSource <NSObject> 
-(void)removeTab:(Tab *)tab; 
@end 

...được bao gồm bất cứ nơi nào bạn định sử dụng đại biểu, ví dụ: đâu đó ở phía trên cùng của nguồn .m bao gồm này:

[self.delegate removeTab:self] 

Nếu trình biên dịch đã chỉ nhìn thấy một về phía trước định nghĩa của TabDelegateDataSource như thế này:

@protocol TabDelegateDataSource; 

Bạn sẽ nhận được lỗi:

error: no known instance method for selector 'removeTab:' 

và không phải là định nghĩa về phía trước dự kiến ​​hơn lỗi liên quan

+1

Đây là vấn đề của tôi. Tôi đã không nhập tiêu đề cho giao thức của mình trong tệp .h này. Cảm ơn ngài ! –

0

Tôi nhập appdelegate.h của mình và lỗi được giải quyết ...

2

Đảm bảo bạn đã không khai báo không chính xác thuộc tính đại biểu trong giao diện (có thể bằng cách sao chép và dán từ tệp khác). Ví dụ:

@protocol SomeDelegate 

... 

@end 

@interface SomeClass 

... 

@property (nonatomic, retain) id<DifferentDelegate>delegate; 


@end 

Dòng trên sẽ gây ra "Không biết phương pháp thể hiện cho bộ chọn ..." do không khớp với giao thức được đính kèm, có thể là lỗi sao chép và dán. Hơn nữa, nó có khả năng ghi đè tham chiếu chính xác đến từ một lớp KHÁC mà nó thực sự thuộc về, cách xa dòng mã này, làm cho nó khó phát hiện.

sửa thông tin trên tuyên bố tài sản của bạn với giao thức định:

@property (nonatomic, retain) id<SomeDelegate>delegate; 
+0

đại biểu phải luôn yếu (không bao giờ giữ lại/mạnh) – SamB

0

Ai đó có thể cần thiết,

SEL selector = NSSelectorFromString(@"removeTab"); 

if([self.delegate respondsToSelector:selector]) { 
    objc_msgSend(self.delegate, selector); 
} 

Lưu ý: Đừng quên này, #import <objc/message.h>

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