Подтвердить что ты не робот

Ошибка 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
4b9b3361

Ответ 1

Я думаю, что это была глупая проблема с Xcode, я перезапустил приложение пару раз, и он закончил работу.

Ответ 2

Теперь я могу воссоздать и исправить эту ошибку по своему усмотрению.

Убедитесь, что заголовок .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:'

а не более ожидаемая ошибка, связанная с прямым определением

Ответ 3

Вы всегда должны проверять свой делегат таким образом, прежде чем вызывать метод, даже с помощью необходимых методов протокола:

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 ];

Ответ 4

Убедитесь, что вы неправильно указали свойство делегата в интерфейсе (возможно, путем копирования и вставки из другого файла). Например:

@protocol SomeDelegate

...

@end

@interface SomeClass

...

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


@end

Вышеприведенная строка вызовет "Нет известного метода экземпляра для селектора..." из-за несоответствия с расширенным протоколом, возможно, с ошибкой копирования и вставки. Кроме того, он, вероятно, переопределяет правильную ссылку из класса DIFFERENT, где он действительно принадлежит, вдали от этой строки кода, что затрудняет его обнаружение.

Исправьте вышеприведенное объявление вашего свойства с предполагаемым протоколом:

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

Ответ 5

Попробуйте переименовать delegate другим, например delegateForTab.

Ваш класс Tab является подклассом UIView, поэтому класс self.delegate self также является подклассом UIView. UIView может иметь свой собственный делегат (он наследует от UIResponder и глубоко от NSObject), и у него нет метода -(void)removeTab. Просто мое личное предположение. Мое решение - переименовать (не найти ответ, может ли он быть подклассифицирован либо еще).

Предложение для использования делегата. Вы должны реализовать protocol и использовать delegate в других диспетчерах представлений, а не в том же классе, который вы его объявляете.:)

Ответ 6

Эта ошибка не является ошибкой компилятора, не так ли? Потому что у меня нет ошибок компилятора с вашим кодом здесь.

Итак, если это ошибка времени выполнения, объявили ли вы <TabDelegateDataSource> в своих классах делегатов следующим образом:

@interface SomeClass : UIView <TabDelegateDataSource>

Если вы это сделали, компилятор должен предупредить вас, если ваш метод экземпляра не найден.

Или вы также можете опубликовать код своего класса делегата для получения дополнительной информации.

P.S. Делегату не должно быть __strong. Вам лучше использовать __unsafe_unretained.

Ответ 7

Я импортирую свой appdelegate.h и исправлена ​​ошибка...

Ответ 8

Возможно, кому-то понадобится

SEL selector = NSSelectorFromString(@"removeTab");

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

Примечание. Не забывайте об этом, #import <objc/message.h>