Ответ 1
Я думаю, что это была глупая проблема с Xcode, я перезапустил приложение пару раз, и он закончил работу.
Мне нужна помощь для отладки моего класса. Я получаю ошибку настолько странную, что я не мог найти ничего подобного, поэтому я просто собираюсь записать большую часть своего кода.
//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
Я думаю, что это была глупая проблема с Xcode, я перезапустил приложение пару раз, и он закончил работу.
Теперь я могу воссоздать и исправить эту ошибку по своему усмотрению.
Убедитесь, что заголовок .h, где это определено...
@protocol TabDelegateDataSource <NSObject>
-(void)removeTab:(Tab *)tab;
@end
... включен, где вы планируете использовать делегат, например. где-то в верхней части источника .m, который включает в себя следующее:
[self.delegate removeTab:self]
Если компилятор видел только прямое определение из файла TabDelegateDataSource:
@protocol TabDelegateDataSource;
Вы получите сообщение об ошибке:
error: no known instance method for selector 'removeTab:'
а не более ожидаемая ошибка, связанная с прямым определением
Вы всегда должны проверять свой делегат таким образом, прежде чем вызывать метод, даже с помощью необходимых методов протокола:
if( self.delegate != nil && [ self.delegate respondsToSelector: @selector( removeTab: ) ]
{
/* Call delegate method... */
}
Выполнение этого даже для требуемых методов добавляет дополнительную безопасность, поскольку эта проверка выполняется во время выполнения.
Кто-то может игнорировать или отключать предупреждения компилятора или обманывать компилятор с помощью типов.
Например:
UILabel * label = [ [ UILabel alloc ] initWithFrame: CGRectZero ];
someTableView.delegate = ( id < UITableViewDelegate > )label;
Кроме того, вы можете использовать performSelector
для вызова фактического метода:
[ self.delegate performSelector: @selector( removeTab: ) withObject: self ];
Убедитесь, что вы неправильно указали свойство делегата в интерфейсе (возможно, путем копирования и вставки из другого файла). Например:
@protocol SomeDelegate
...
@end
@interface SomeClass
...
@property (nonatomic, retain) id<DifferentDelegate>delegate;
@end
Вышеприведенная строка вызовет "Нет известного метода экземпляра для селектора..." из-за несоответствия с расширенным протоколом, возможно, с ошибкой копирования и вставки. Кроме того, он, вероятно, переопределяет правильную ссылку из класса DIFFERENT, где он действительно принадлежит, вдали от этой строки кода, что затрудняет его обнаружение.
Исправьте вышеприведенное объявление вашего свойства с предполагаемым протоколом:
@property (nonatomic, retain) id<SomeDelegate>delegate;
Попробуйте переименовать delegate
другим, например delegateForTab
.
Ваш класс Tab
является подклассом UIView
, поэтому класс self.delegate
self
также является подклассом UIView
. UIView
может иметь свой собственный делегат (он наследует от UIResponder и глубоко от NSObject), и у него нет метода -(void)removeTab
. Просто мое личное предположение.
Мое решение - переименовать (не найти ответ, может ли он быть подклассифицирован либо еще).
Предложение для использования делегата. Вы должны реализовать protocol
и использовать delegate
в других диспетчерах представлений, а не в том же классе, который вы его объявляете.:)
Эта ошибка не является ошибкой компилятора, не так ли? Потому что у меня нет ошибок компилятора с вашим кодом здесь.
Итак, если это ошибка времени выполнения, объявили ли вы <TabDelegateDataSource>
в своих классах делегатов следующим образом:
@interface SomeClass : UIView <TabDelegateDataSource>
Если вы это сделали, компилятор должен предупредить вас, если ваш метод экземпляра не найден.
Или вы также можете опубликовать код своего класса делегата для получения дополнительной информации.
P.S. Делегату не должно быть __strong
. Вам лучше использовать __unsafe_unretained
.
Я импортирую свой appdelegate.h и исправлена ошибка...
Возможно, кому-то понадобится
SEL selector = NSSelectorFromString(@"removeTab");
if([self.delegate respondsToSelector:selector]) {
objc_msgSend(self.delegate, selector);
}
Примечание. Не забывайте об этом, #import <objc/message.h>