Unrecognized selector sent to instance, performSelector:withObject:afterDelay: and Delegates
-
21-12-2019 - |
Question
using xCode 5 with ARC, Objective-C
I have simple program, where I add additional class with protocol for new delegate (very simple).
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
and
in ViewController.h I add
#import "ArrayGenerator.h"
@interface ViewController : UIViewController <ArrayGeneratorDelegate>
@end
in ViewController.m I add
...
- (void)viewDidLoad
{
[super viewDidLoad];
ArrayGenerator *ag = [[ArrayGenerator alloc ]init];
ag.delegate = self;
[ag ArrayGenerator];
}
...
-(void)StartTask:(NSMutableArray*)array{
NSLog( @"StartTask" );
}
So I achieve, that after running app in 1 second in Log i could see "StartTask", but instead of this i simply got Exception like
DelegatesWithDelay[2240:90b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ArrayGenerator StartTask:]: unrecognized selector sent to instance 0x8b55200'
Spend a lot of time to find something similar problem with described solution (here and other sites, but nothing from that not help's).
Also find an alternative solution:
instead of [self performSelector:mySelector withObject:array afterDelay:1];
I call to [NSTimer scheduledTimerWithTimeInterval:3.0 target:self.delegate selector:mySelector userInfo:nil repeats:NO];
- and all it's work fine, but I want to know why first variant with performSelector:withObject:afterDelay:
not work??? (Question)
Also try to:
- recreate project - almost different - not help -same problem with this method, but with NSTimer - al works;
- change @property attributs from (nonatomic, weak), to (nonatomic, release) (as was recommended in some solution to similars problem - not help
- try to use another variants of performSelector methods - not helps
- try to change
mySelector
to@selector(StartTask:)
- not helps
and so on....nothing help, maybe i miss something?
Solution
It should be this:
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];
});
}
Your self (ArrayGenerator
) has no selector StartTask
, but your delegate does.
OTHER TIPS
Finally I found real reason for this exception (that described in question).
The method performSelector:withObject:afterDelay:
is defined on NSObject - but id works for more than just NSObject (so i must to be more specific than just 'id').
What need to change -
@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
Actually answer found here