Objective-c using thread causes: target does not implement selector - objective-c

As I am pretty new to ObjC I'm stuck to the following issue:
I have a function downloadFile
-(void) downloadFile:(NSMutableArray*)paramArray withDict:(NSMutableDictionary*)options
{
//do stuff
}
I want to start this as a thread, and therefore I use this line of code:
NSThread* dLoad = [[NSThread alloc] initWithTarget:self selector:#selector(downloadFile:) object:nil];
[dLoad start];
It throws me the following error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSThread initWithTarget:selector:object:]: target does not implement selector (*** -[LaunchDownload downloadFile:])'
What am I missing over here?

I believe you're not providing enough arguments to your thread. The method you implemented has the signature downloadFile:withDict:, but you're only providing downloadFile:. You should give it the correct selector name.
Keep in mind that you will probably run into trouble anyway - the NSThread class reference specifies that methods you call this way must take only one argument. I'd recommend either converting your two arguments to a single NSDictionary that your method parses out or rethinking how you're dispatching this thread.

The method name is downloadFile:withDict: and not downloadFile: .

Related

auto scroll uipickerview when button is clicked

I am using a UIPickerView to display answers to a question. There needs to then be a button to reveal the correct answer if the user cannot work it out. I have tried the below, but the app crashes. How can i autoscroll to the correct answer?
-(void)reveal {
[myPickerView selectRow:0 inComponent:0 animated:YES];
}
EDIT: Yes i am just trying to get it to scroll to the first answer in the above example :)
[ExcerciseController reveal:]: unrecognized selector sent to instance 0x68398f0
2012-10-30 14:57:21.673 English[20786:f803] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ExcerciseController reveal:]: unrecognized selector sent to instance 0x68398f0'
* First throw call stack:
(0x1397022 0x108ccd6 0x1398cbd 0x12fded0 0x12fdcb2 0x1398e99 0x1f214e 0x1f20e6 0x298ade 0x298fa7 0x298266 0x2173c0 0x2175e6 0x1fddc4 0x1f1634 0x21a3ef5 0x136b195 0x12cfff2 0x12ce8da 0x12cdd84 0x12cdc9b 0x21a27d8 0x21a288a 0x1ef626 0x2c5d 0x2b85)
terminate called throwing an exception[Switching to process 20786 thread 0xf803]
Now, that the error/crash message is visible, it turns out that the error is not in how you call the picker's method. It is how you invoke reveal.
You call reveal with some object. Or you call it by passing a selector. However, the current selector that you are calling is reveal: but the methods name is reveal without any parameter. reveal: would require one parameter.
Wherever you call it, make sure that you call reveal and not reveal:
I assume you set the selector either in interface builder or when creating the button programmatically. That is the place where you made the mistake.
Some background:
The error message tells you what you need to know. A method name is called selector in Objective-C at runtime. In some literature you will find the wording of a message (named reveal: in your case) is sent to a receiver named ExcerciseController in your case.
Objective-C is polymorph. That means that reveal (called without any parameters) refers to another method implementation than reveal: (called with one parameter) or even reveal:: (called with three parameters).
myPickerView may not be the instance of UIPickerView as UIPickerView responds to selector - (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated
Or you have to check how the method reveal is invoked.
please try to post the crash description,Need more blocks of code to answer it :)
However just try the below code
myPickerView.delegate = self;
[myPickerView reloadAllComponents];
[myPickerView selectRow:0 inComponent:0 animated:YES];

How to catch unrecognized selector sent to instance exception?

I am getting after some time unrecognized selector sent to instance exception. When i get this i want just skip it and my app should work.
However i don't know how to catch. As this don't catch:
#property(nonatomic,retain) UIButton *button;
#try{
if(button.currentBackgroundImage == nil){//rises exception
}
}#catch(NSException *e){
}
How i could handle this ?
Thanks.
The technique I use and see often is: instead of catching the exception, check if the object responds to the selector:
if(![button respondsToSelector:#selector(currentBackgroundImage)] || button.currentBackgroundImage == nil) {
// do your thing here...
}
If you are getting this exception, it means there is a design flaw, a bug in your code. Patching it by ignoring the exception is not the right thing to do. Try to pin down why you are sending the wrong message to the wrong object instead. Your code will become more robust and maintainable.
Also, sometimes you get this exception when the object originally was of the right type, but is halfway in the process of being deallocated. Watch out!
If you still want to bypass the exception, read Apple's docs where it explains the multi-step process by which messages are bound to method implementations at run time. There is at least two places where you can catch it by overriding NSObject's default behavior.
I understand the answers telling you to prevent the unrecognized selector since that is the preferred method.
But in the case where you do not have that option (such as in my case, Cocoa internals messing up further down the call stack) you can indeed catch the unrecognized selector as you tried.
Proof of concept code:
// Do a really bad cast from NSObject to NSButton
// to get something to demonstrate on
NSButton *object = (NSButton*)[[NSObject alloc] init];
#try{
// Log the description as the method exists
// on both NSObject and NSButton
NSLog(#"%#", [object description]);
// Send an unrecognized selector to NSObject
[object bounds];
} #catch(NSException *e){
NSLog(#"Catch");
} #finally {
NSLog(#"Finally");
}
// Print the description to prove continued execution
NSLog(#"Description again: %#", [object description]);
Output:
2019-02-26 14:11:04.246050+0100 app[46152:172456] <NSObject: 0x60000000a6f0>
2019-02-26 14:11:04.246130+0100 app[46152:172456] -[NSObject bounds]: unrecognized selector sent to instance 0x60000000a6f0
2019-02-26 14:11:04.246226+0100 app[46152:172456] Catch
2019-02-26 14:11:04.246242+0100 app[46152:172456] Finally
2019-02-26 14:11:04.246258+0100 app[46152:172456] Description again: <NSObject: 0x60000000a6f0>
As you can see the exception is still logged to the console, but the code execution continues.

Array not retaining properly?

I get the following error when running my App:
2011-09-02 15:38:44.157 TheApp[9973:207] -[NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x4b28990
2011-09-02 15:38:44.160 TheApp[9973:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x4b28990'
And Xcode marks the line in this function in green:
- (void)oneCheckAndSetStrokes {
playerOneScoreNum.text = [playerOneScore objectAtIndex:(11)]; }
Therefore I'm guessing something is messed up with the Array. After som research I came across a lot of posts like this one: NSMutableArray : unrecognized selector sent to instance which seems to inticate that the error occurs when the Array is not being retain properly (hence my title).
So I'm trying to retain the Array in the file in wich it is initiated (which by the way is not the same file as the code above. The Array is also defined in another file, Globals.h, and then imported), in the following way:
- (void)viewDidLoad {
[super viewDidLoad];
playerOneScore = [[NSMutableArray alloc] initWithCapacity:19];
[playerOneScore retain]; }
This would solve the problem according to the post refered to earlier, but in my case it does not. Has anyone encountered something similar? It seems like I'm missing something trivial here.
The error you got has nothing to do with retain, you got that error because at this line:
playerOneScoreNum.text = [playerOneScore objectAtIndex:(11)];
you are trying to set a string property using a number object! You have to use "stringValue", in this way:
playerOneScoreNum.text = [[playerOneScore objectAtIndex:11] stringValue];
ps: wrapping the index (11) with parenthesis is useless :P

Objective-C Declaring object as a totally different class than what I declared

In a method I wrote, I'm declaring an instance of class 'A' and calling a method on it. At run time, when the method runs, my app crashes. It says an unrecognized selector was sent to an instance of class 'B' even though I declared an instance of 'A'. I read somewhere that I may not be managing my memory correctly so it's sending the method to another class, but I'm using ARC so that shouldn't even be a problem. Help would be much appreciated!
The error I'm getting:
2011-08-27 01:25:49.859 Intelligenda[49385:bc03] PVC: <HomeViewController: 0x59359e0>
2011-08-27 01:25:49.945 Intelligenda[49385:bc03] -[HomeViewController addNewClass:]: unrecognized selector sent to instance 0x59359e0
2011-08-27 01:25:49.947 Intelligenda[49385:bc03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[HomeViewController addNewClass:]: unrecognized selector sent to instance 0x59359e0'
and the method that's being called:
-(IBAction)done:(id)sender{
[teacherName resignFirstResponder];
[className resignFirstResponder];
IntelligendaAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
UINavigationController *nav = delegate.navController;
[nav popViewControllerAnimated:YES];
ClassesViewController *classesParentViewController = (ClassesViewController *) nav.topViewController;
ClassIG *theNewClass = [[ClassIG alloc] init];
theNewClass.className = className.text;
theNewClass.teacherName = teacherName.text;
NSIndexPath *indexPath;
theNewClass.subject = [tableView cellForRowAtIndexPath:indexPath].textLabel.text;
// add reminder to array
NSLog(#"PVC: %#", [classesParentViewController description]);
[classesParentViewController addNewClass:theNewClass];
}
Declaring, say, a pointer NSArray* fred does nothing (other than a sprinkling of compile-time warning messages) to assure that fred is an NSArray. It's what you assign to fred that counts. If you assign an NSDateFormatter, then that's what fred is.
Your assumption that the application delegate's navigation controller has a ClassesViewController on top is clearly flawed. It has a HomeViewController on top. Your structure looks like it may be a little complicated, given that you have a button somewhere wired up to an action in some other part of your controller classes, so there could be a bunch of causative reasons.
First things to check: if you're instantiating buttons programmatically then did you accidentally add the button to the wrong controller? If you're designing everything using the graphical interface designer but keeping it in a single NIB, is it possible you copied and pasted a button and forgot to change what it's wired to?
If you can end up with multiple navigation controllers, are you sure the one held by the application delegate is currently on screen?
the short answer is that typecasting and type conversions are an exercise for the programmer in objc.
read my answer here:
Passing NSNumber* to NSString* expected-parameter does not cause compiler warning / error
...for some more information as to how declaring/casting a variable of an object differs from other languages, and how you can detect those cases.

NSInvalidArgumentException... how do I define the arguments correctly?

I'm getting this exception on the following code. I think it's because I have not defined the two incoming parameter types. They are local; so how do I define them (and where).
Error: 2011-04-27 11:18:03.226
PointPeek[174:707] * Terminating app
due to uncaught exception
'NSInvalidArgumentException', reason:
'+[SQLiteDB addRecordToDatabase::]:
unrecognized selector sent to class
0x1fe70'
Here's the calling line of code:
[SQLiteDB addRecordToDatabase:
symbol.data: symbol.typeName];
and here's the method I'm calling:
- (void) addRecordToDatabase:data: typeName {
NSString *insertCommand = [NSString stringWithFormat:#"INSERT INTO CardData (CARD_ID, CARD_NAME, CODE_VAL) VALUES ('/%#', '/%#', '/%#')", data, #"Test Card", typeName];
if(sqlite3_open_v2(cDatabasePath, &db, SQLITE_OPEN_READWRITE, NULL) == SQLITE_OK) {
}
Error: 2011-04-27 11:18:03.226
PointPeek[174:707] * Terminating app
due to uncaught exception
'NSInvalidArgumentException', reason:
'+[SQLiteDB addRecordToDatabase::]:
unrecognized selector sent to class
0x1fe70'
Basically, the "unrecognized selector sent to..." message means you tried to tell an object (or class) to do something it doesn't know how to do. ("selector" is another name for method).
You defined your method of the SQLiteDB class as an instance method:
- (void) addRecordToDatabase:data: typeName;
We know that because of the - in the method name (see Methods and Messaging and Class Interface). In the error message you got, notice that it began with a +, which means you attempted to call a method on the SQLiteDB class itself, rather than on an instance of that class.
In other words, you attempted to do this:
[SQLiteDB addRecordToDatabase: symbol.data: symbol.typeName];
when you needed to do something like this:
SQLiteDB *db = [[[SQLiteDB alloc] init] autorelease]; // an instance
[db addRecordToDatabase: symbol.data: symbol.typeName];
(Note that the previous 2 lines of code aren't all that useful in and of themselves. Presumably, instead of creating an instance of SQLiteDB in this method, you'd have it as an instance variable).
[SQLiteDB addRecordToDatabase: symbol.data: symbol.typeName];
That'd assume that addRecordToDabase:: is a class method, not an instance method.
Furthermore, that is an awful name for a method. Try something like:
- (void)addRecordWithData:(NSData*)aData andType:(NSString*)aType;
That is, bare :s are to be avoided and you should always specify the type of the parameter (and not fall back to id as you did here).
Finally, why aren't you using Core Data or, at the very least, FMDB? Raw SQLite is a waste of time.
SQLite is harder to write code for than Core Data, most likely. If you are a newbie to both, Core Data is a better return on investment of your time.
In any case, the questions in your comment indicate that you really need to start by understanding Objective-C. Apple provides an excellent language guide.