Нераспознанный селектор отправлен экземпляру, PerformSelector:withObject:afterDelay: и делегатам

использование xCode 5 с ARC, Objective-C

У меня есть простая программа, в которой я добавляю дополнительный класс с протоколом для нового делегата (очень просто).

ArrayGenerator.h

#import <Foundation/Foundation.h>
@protocol ArrayGeneratorDelegate <NSObject>
@required
-(void)StartTask:(NSMutableArray*)array;
@end

@interface ArrayGenerator : NSObject
@property (nonatomic, weak) id <ArrayGeneratorDelegate> delegate;
-(void)ArrayGenerator;
@end

ArrayGenerator.m

#import "ArrayGenerator.h"
@implementation ArrayGenerator

-(void) ArrayGenerator{
//create selector for method in Protocol
SEL mySelector = @selector(StartTask:); 
if (self.delegate && [self.delegate respondsToSelector:@selector(StartTask:) ] ){   
    //call to method    
    [self performSelector:mySelector withObject:array afterDelay:1];
}
@end

и

в ViewController.h я добавляю

#import "ArrayGenerator.h"
@interface ViewController : UIViewController <ArrayGeneratorDelegate>
@end

в ViewController.m я добавляю

 ...
 - (void)viewDidLoad
{
[super viewDidLoad];
ArrayGenerator *ag = [[ArrayGenerator alloc ]init];
ag.delegate = self;
[ag ArrayGenerator];
}
...
-(void)StartTask:(NSMutableArray*)array{
NSLog( @"StartTask" );
}

Итак, я добиваюсь, чтобы после запуска приложения за 1 секунду в журнале я мог видеть «StartTask», но вместо этого я просто получил исключение, например

DelegatesWithDelay[2240:90b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ArrayGenerator StartTask:]: unrecognized selector sent to instance 0x8b55200'

введите здесь описание изображения

Потратить уйму времени на поиск похожей проблемы с описанным решением (здесь и на других сайтах, но ничего из этого не помогает).

Так же нашел альтернативное решение: вместо [self performSelector:mySelector withObject:array afterDelay:1]; звоню на [NSTimer scheduledTimerWithTimeInterval:3.0 target:self.delegate selector:mySelector userInfo:nil repeats:NO]; - и все нормально работает, но я хочу знать, почему первый вариант с performSelector:withObject:afterDelay: не работает??? (Вопрос)

введите здесь описание изображения

Также попробуйте:

  • пересоздать проект - почти другой - не помогает - та же проблема с этим методом, но с NSTimer - все работает;
  • измените атрибуты @property с (nonatomic, weak) на (nonatomic, release) (как было рекомендовано в некоторых решениях для подобных проблема - не помогает
  • попробуйте использовать другие варианты методов PerformSelector - не помогает
  • попробуйте изменить mySelector на @selector(StartTask:) - не помогает

и так далее....ничего не помогает, может я что-то пропустил?


person hbk    schedule 29.07.2014    source источник
comment
попробуйте заменить: [self PerformSelector:mySelector withObject:array afterDelay:1]; by [self.delegate PerformSelector:mySelector withObject:array afterDelay:1];   -  person Ali Abbas    schedule 29.07.2014
comment
если я поставлю [self.delegate], я могу использовать только `[self.delegate PerformSelector:mySelector];` или `[self.delegate PerformSelector:mySelector withObject:someObject];`, но без задержки, и да, это работает   -  person hbk    schedule 29.07.2014
comment
ios 9.1 поддерживает arm64 после этой причины ошибки [делегат NSTaggedPointerString] отправлен неизвестный селектор .. пожалуйста, помогите мне   -  person Patel Maulik    schedule 25.11.2015


Ответы (2)


Это должно быть так:

if (self.delegate && [self.delegate respondsToSelector:@selector(StartTask:) ] ){     
     NSInteger delay = 1;
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          [self.delegate performSelector:mySelector withObject:array];
     });
}

У вашего «я» (ArrayGenerator) нет селектора StartTask, но есть у вашего делегата.

person Nate Lee    schedule 29.07.2014
comment
да, это решение работает нормально, я понимаю, в чем проблема была - person hbk; 29.07.2014
comment
Да, и для соглашения: измените StartTask на startTask и измените свой метод ArrayGenerator на что-то другое. Вы можете запутаться, хотите ли вы NSObject или метод. - person Nate Lee; 29.07.2014
comment
ios 9.1 поддерживает arm64 после этой причины ошибки [делегат NSTaggedPointerString] отправлен неизвестный селектор .. пожалуйста, помогите мне - person Patel Maulik; 25.11.2015

Наконец я нашел реальную причину этого исключения (описанного в вопросе).

Метод performSelector:withObject:afterDelay: определен для NSObject, но id работает не только с NSObject (поэтому я должен быть более конкретным, чем просто 'id').

Что нужно изменить -

@interface ArrayGenerator : NSObject
@property (nonatomic, weak) id <ArrayGeneratorDelegate> delegate;
-(void)ArrayGenerator;
@end

to

@interface ArrayGenerator : NSObject
@property (nonatomic, weak) NSObject <ArrayGeneratorDelegate> delegate;
-(void)ArrayGenerator;
@end

На самом деле ответ найден здесь

person hbk    schedule 30.07.2014
comment
ios 9.1 поддерживает arm64 после этой причины ошибки [делегат NSTaggedPointerString] отправлен неизвестный селектор .. пожалуйста, помогите мне - person Patel Maulik; 25.11.2015