NSInvalidArgumentException: +[NSThread detachThreadSelector:toTarget:withObject:]: unrecognized selector sent to class
I've recently started programming in Objective-C, but I have a few years of experience in Java, C++ and C.
Yet, I've managed to run into problems making a generalized "createThread" method. This is my console output, in XCode:
[Session started at 2010-06-14 16:42:22 +0200.]
2010-06-14 16:42:22.104 Main[196:903] +[NSThread detachThreadSelector:toTarget:withObject:]: unrecognized selector sent to class 0xa0b61398
2010-06-14 16:42:22.108 Main[196:903] Caught NSInvalidArgumentException: +[NSThread detachThreadSelector:toTarget:withObject:]: unrecognized selector sent to class 0xa0b61398
The Debugger has exited with status 0.
Main.m:
#import "Main_Prefix.pch"
#import "Thread.h"
void helloWorld(){
NSLog(@"Hello, world!");
}
int main(int argc, char* argv){
NSAutoreleasePool* memoryPool = [[NSAutoreleasePool alloc] init];
Thread* thread = [[Thread alloc] init];
@try{
[thread setUnderlyingProcess:&helloWorld];
[thread executeThread];
}@catch(NSException* ne){
NSLog(@"Caught %@: %@", [ne name], [ne reason]);
}@finally{
[thread release];
[memoryPool drain];
}
return 0;
}
Thread.h:
@interface Thread : NSObject
void* underlyingProcess;
-(void)setUnderlyingProcess:(void*)process;
-(void)executeThread;
@end
Thread.m:
#import "Thread.h"
@implementation Thread
-(void)setUnderlyingProcess:(void*)process{
underlyingProcess = process;
}
-(void)executeThread{
[NSThread detachThreadSelector: @selector(underlyingProcess) toTarget: self withObject: nil];
}
@end
I really hope that someone can help me :).
You have the right idea here, and the incorrect syntax. The 'unrecognized selector' means that you've tried to send a message to an object that doesn't have the appropriate entry point to respond to that message.
I've never used the NSThread class, so I don't know those APIs. I'm away from the Mac at the moment (on Windows7, yikes). I think it's the underProcess that's causing you grieve. Try @selector(underlyingProcess:) and maybe you'll be lucky. Otherwise I'll look at this tomorrow (It's 12:30 at night here in California).
Thanks a lot for your reply, unfortunately I haven't had any luck using it so far.
Anyway, I made some changes and optimized the code :).
I've uploaded the files to a pastebin, for ease of reading.
With the new code, I get this exception instead:
//Start of exception
[Session started at 2010-06-15 17:16:26 +0200.]
2010-06-15 17:16:26.467 ThreadManager[3955:903] Caught NSInvalidArgumentException: *** -[NSThread initWithTarget:selector:object:]: target does not implement selector (*** -[Thread process:])
The Debugger has exited with status 0.
//End of exception
Here's ThreadManager.m:
And here's Thread.h:
Thread.m:
Don't take notice of the references to ThreadPool. This is just a NSMutableArray wrapper I made, to make a NSMutableArray serve as the HashMap class does in Java.
Also, this application isn't running in a garbage collected environment, so if you want I would like you to check if I'm doing my memory management correct, so I can avoid memory leaks :).
I've taken your first code and got him to work. You can download it from: http://clanmills.com/files/WeeThreads.zip
Take a look. I think you'll understand it OK without discussion. If not, please come back and ask again - or contact me directly at robin@clanmills.com.
I'm at work, so I don't have time at the moment to look at your NSMutableArray stuff at the moment. I'll look this evening.
Thanks a bunch :). I haven't tried to implement it myself in my current code, but I assume that I'll get it working :). But. - Just to make sure I understand the code right, the "iAmYourThread" void, is used to dereference the "underlyingProcess", so that the target ("self") in the implemented "executeThread" void matches the location of the process that needs execution, right? Oh, and the call to the "underlyingProcess("...")" will actually call the void pointed to by the underlyingProcess pointer, right?
Yes.
---
underlyingProcess("called from executeThread") ;
is "straight C". You're calling directly into your HelloWorld code (just above main()).
is subtle. You're saying run the method "iAmYourThread" on a new thread (and of course iAmYourThread then makes a direct call to HelloWorld().
---
I took a little sleep between the threaded call and the direct for two reasons:
1) I'm not sure that printf is thread safe (although I think he is)
2) I wanted to give the thread enough time to actually get the job done before the whole program finished!
---
-(void) iAmYourThread
{
underlyingProcess("called from iAmYourThread") ;
}
-(void)executeThread{
[NSThread detachNewThreadSelector: @selector(iAmYourThread) toTarget: self withObject: nil];
sleep(1);
underlyingProcess("called from executeThread") ;
}
-(void)executeThread{
[NSThread detachNewThreadSelector: @selector(iAmYourThread) toTarget: self withObject: nil];
sleep(1);
underlyingProcess("called from executeThread") ;
}
Alright, thanks :).
I've also got it implemented in my own code now, - and it works great :).
Glad to be of help.
If there's something you want me to look at with the NSMutableArray stuff, let me know. However I think we're done here for now (and I'll deal with my open source stuff this evening).
Glad to be of help.-clanmills
And you certainly have been :). And I must agree with you, I also think that we're done here.... for now.