NSInvalidArgumentException... how do I define the arguments correctly? - objective-c

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.

Related

Why does valueForKey throw an exception when used on dispatch_queue_t instance variable?

This is for unit testing purposes only
I'm trying to access a dispatch_queue_t that is a protected instance variable of an objective C object for unit testing purposes. I'm using valueForKey to access the protected instance variables that are objects, is there an equivalent call I can make for dispatch_queue_t?
Thank you
Edit: I've read that access to these values is possible, I just can't find a explanation of how.
Edit2: When I try calling valueForKey I get
2013-09-24 14:17:35.235 MyApp[7729:a0b] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ valueForUndefinedKey:]: this class is not key value coding-compliant for the key _queue.'
Edit3: I just tested and realized it should work with structs, the one that is throwing the exception is the retrieval of a dispatch_queue_t
Edit4: This was in code that is using Automatic Reference Counting
Use the same -valueForKey: as for objects.
Calling -valueForKey: will always return you an object, but in case of accessing non-object types, the value is wrapped in NSValue object. In case of structs it's NSValue directly, in case of numbers (int, float) it uses NSNumber subclass.
After you got NSValue, this is how you unwrap the struct:
NSValue *value = [object valueForKey:#"key"];
struct Something s;
[value getValue:&s];
// `s` contains the desired struct
Solution found:
The alternative way to access the instance variable is with the following code using object_getIvar:
Ivar queueIvar = class_getInstanceVariable([_myObject class], "_queue");
_privateQueue = (__bridge dispatch_queue_t)(object_getIvar(_myObject, queueIvar));

Strange BAD_ACCESS error

This may sound a newbie question however I'm new iOS dev,
recently I've switched to ARC and have got following issue in my code. I've implemented a class with following init method
- (id)init
{
self = [super init];
if (self) {
TokenManager* tokenManager = [[TokenManager alloc] initWithApikey:<my valid token>];
mRequest = [[GeoCodingRequest alloc] initWithApikey:apiKey withOptions:nil tokenManager:tokenManager];
mRequest.delegate = self;
}
return self;
}
where mRequest in interface is declared like this __strong GeoCodingRequest* mRequest;
In my other method of the same class I send a message to mRequest like this
[mRequest findObject:<some valid array> around:<some valid location> withDistance:<some valid radius>];
When the message is sent to object app crashes with following message
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString appendRequestWithToken:]: unrecognized selector sent to instance 0x8974640'
findObject: around: withDistance: - is a method from public library, so I've not access to its implementation.
Please help me to understand why this crash happens ?!
I guess it is coming from ARC _strong/_weak qualifier usage or smth.
The message means that mRequest has been deallocated has that a string is now using the memory that had previously been allocated for mRequest.
You should run your app with Zombies enabled to understand when mRequest gets deallocated.
It looks like the tokenManager isn't retained by the request (which is a bug in the library). As it isn't retained anywhere, the tokenManager is deallocated and a new object (here an instance of NSString) may be allocated at the same place.
You need to store the tokenManager in a strong instance variable (just as mRequest) in order to retain it as long as the request needs it.
if you have any weak references try to use
MyObject * strongMyObject = weakMyObject;
if(strongMyObject){
NSLog(#"This is not released");
}
It's a good practice when you have weak references. Try this.

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.

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

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: .