"unrecognized selector sent to instance" for NSArrayI - objective-c

I have the following code which gives the "unrecognized selector sent to instance" error for the NSArray. I've not been able to figure this out and feel its something simple I'm missing here. I can post more if needed.
Quote *myQuote;
NSArray *myQuotes = theSubject.quotes;
//START LOOP HERE
for (myQuote in myQuotes){
NSLog(#" excerpt = %#", myQuote.excerpt);
NSLog(#" desc2 = %#", myQuote.desc2);
NSLog(#" quote_date = %#", myQuote.quote_date);
NSLog(#" myQuote = %#", myQuote);
I believe the problem is in this function which returns an array of Quotes:
- (NSArray *) getQuotesFromSubId:(NSInteger )subId {
QuotesAppDelegate *appDelegate = (QuotesAppDelegate *)[[UIApplication sharedApplication] delegate];
self.quoteMaps = [appDelegate quoteMaps];
self.quotes = [appDelegate quotes];
//get the quote_ids from quote_map for this subject_id
NSString *stringOfSubjectId = [NSString stringWithFormat:#"%ld", (long)subId];
NSPredicate *filterSubjectId = [NSPredicate predicateWithFormat:#"subject_id == %#", stringOfSubjectId];
NSArray *quoteMapSection = [self.quoteMaps filteredArrayUsingPredicate:filterSubjectId];
NSMutableArray *quoteSection = [[NSMutableArray alloc] init];
NSArray *quoteToAdd = [[NSArray alloc] init];
for (QuoteMap *qm in quoteMapSection){
//get the quote_ids from quote_map for this subject_id
NSPredicate *filter = [NSPredicate predicateWithFormat:#"quote_id == %#", qm.quote_id];
quoteToAdd = [self.quotes filteredArrayUsingPredicate:filter];
[quoteSection addObject:quoteToAdd];
}
return quoteSection;
}
This is where I call it:
QuotesAppDelegate *appDelegate = (QuotesAppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *myQuotes = [appDelegate getQuotesFromSubId:selectedSubject.subject_id];
NSMutableArray *mArray = [appDelegate createMutableArray:myQuotes];
selectedSubject.quotes = mArray;
NSMutableArray *mutableArray = [appDelegate createMutableArray:myQuotes];
selectedSubject.quotes = mutableArray;
I got the following error
2016-02-23 00:24:20.383 Quotes[10631:3698114] -[__NSArrayI excerpt]: unrecognized selector sent to instance 0x15ebbeff0
2016-02-23 00:24:29.164 Quotes[10631:3698114] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI excerpt]: unrecognized selector sent to instance 0x15ebbeff0'
*** First throw call stack:
(0x182b55900 0x1821c3f80 0x182b5c61c 0x182b595b8 0x182a5d68c 0x100078b2c 0x1000642d0 0x187cb17f4 0x187cb1f8c 0x187b9fc90 0x187ba2e88 0x187977284 0x187883394 0x187882e90 0x187882d18 0x185259c00 0x10011dbb0 0x100123658 0x182b0cbb0 0x182b0aa18 0x182a39680 0x183f48088 0x1878b0d90 0x100040398 0x1825da8b8)
libc++abi.dylib: terminating with uncaught exception of type NSException

You are sending -excerpt to the members (myQuote) of myQuotes. The runtime says that NSArray (NSArrayI is an internal subclass) instances cannot understand -excerpt.
So the type of the member is NSArray. We cannot know, why you have instances of NSArray in the array MyQuotes, because we do not see that code. Likely that happened when you tried to add new quotes to the quotes property and incidentally added the whole array instead of its members.
To your edit:
This is wrong:
NSArray *quoteToAdd = [[NSArray alloc] init]; // This is an array. It identifier should be quote*s*ToAdd
// BTW: This above code is meaningless, because you do not need to create an array instance. Simply omit "[[NSArray alloc] init]". But this is not your problem.
for (QuoteMap *qm in quoteMapSection){
…
quoteToAdd = [self.quotes filteredArrayUsingPredicate:filter]; // filtered array returns an *array*
[quoteSection addObject:quoteToAdd]; // You add the *array* instead of the member of the array.
}
What you get back is an array. Then you add the array itself (not its members) to the existing array. As result you get an array that contains an array.
Simply change …
[quoteSection addObject:quoteToAdd];
… to:
[quoteSection addObjectsFromArray:quoteToAdd];
(And change the reference name to a plural form for better readability.)

Related

setObjectForKey: object cannot be nil in mutableArray

Greeting. I have code like below, I want to add multiple value to the same key in the dictionary.
if ([_sectionContents objectForKey:AddKey] != nil) {
//Already exist a value for the key
id object = [_sectionContents objectForKey:AddKey];
NSMutableArray *objectArray;
if ([object isKindOfClass:[NSMutableArray class]]) {
objectArray = (NSMutableArray *)object;
} else {
NSMutableArray *objectArray = [[NSMutableArray alloc] init];
}
[objectArray addObject:course];
[_sectionContents setObject:objectArray forKey:AddKey];
} else {
//No value for the key
[_sectionContents setObject:[NSArray arrayWithObjects:course,nil] forKey:AddKey];
}
However, I got the error
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** setObjectForKey: object cannot be nil
I figure out it is because of line
[_sectionContents setObject:objectArray forKey:AddKey];
And also I got the warning like objectArray is not used
I don't understand it because I did use objectArray for adding element in it. Why is that please?
When you write
NSMutableArray *objectArray = [[NSMutableArray alloc] init];
you're creating a new variable local to the inside of that 'else' statement. As such, it is created then immediately released, because there is nothing following it in the else statement.
You want to update the variable rather than re-create it - try replacing the rogue line with
objectArray = [[NSMutableArray alloc] init];
(When we don't specify the type e.g. 'NSMutableArray *', we assign to an existing variable, rather than establishing a new one.)
This is because you have two objectArray instead of one
if ([_sectionContents objectForKey:AddKey] != nil) {
...
// first one
NSMutableArray *objectArray;
if ([object isKindOfClass:[NSMutableArray class]]) {
objectArray = (NSMutableArray *)object;
} else {
// second one (*)
NSMutableArray *objectArray = [[NSMutableArray alloc] init];
// *** Correct Solution ***
objectArray = [[NSMutableArray alloc] init];
}
...
} else {
...
}
(*) You've redefined your object array incorrectly in your else clause of your if inside the main if ([_sectionContents objectForKey:AddKey] != nil) {. If object isn't kinda NSMutableArray you get to the else which initialize new ObjectArray and not the one defined at the top of your if statement.

NSMutable array error & showAnnotations

I have the following situation. I developed an app that frequently retrieves values for POI's that I want to show as annotations on a map. For this I wrote the method below, called after when a new set of POIs was retrieved:
-(void)showAnnotation{
[self removeAllPinsButUserLocation];
annotationArray = [[NSMutableArray alloc] init];
for (Poi *poi in [parser.pois allValues]) {
myAnnotation *arr = [[myAnnotation alloc] init];
arr.title = [NSString stringWithFormat:#"%# (%#)",poi.description, sensor.name];
arr.subtitle = [NSString stringWithFormat:#"%#, %# %#",poi.street, poi.postalcode, poi.city];
arr.coordinate = CLLocationCoordinate2DMake(poi.lattitude, poi.longitude);
[annotationArray addObject:arr];
arr = nil;
}
[self.mapView addAnnotations:annotationArray];
[self.mapView showAnnotations:annotationArray animated:NO];
}
Problem is that I get an error (Terminating app due to uncaught exception 'NSGenericException', reason: '* Collection <__NSArrayM: 0x14ebe9b0> was mutated while being enumerated.')
However only if I set animated:NO in the last line, but not when set to animated:YES...
Does anyone have an answer for this?
Thanks for replying!
Eelco

Objective-C: Static NSDictionary throws NSInvalidArgumentException when I add to it

I have a method that is supposed to take an NSManagedObject, copy its attributes into a dictionary, then add the dictionary to an NSMutableArray in a static NSMutableDictionary with NSManagedObjectID keys. The problem is that it crashes when I try to add to a static NSMutableDictionary and only works if I make one on the spot.
The problem is definitely related to the static NSMutableDictionary changes because I do not get the exception if I use a non-static dictionary. It's defined like this (above #implementation):
static NSMutableDictionary* changes = nil;
And here is the method:
+ (void)acceptChange: (NSManagedObject *)change{
if (!changes){
NSLog(#"Making new changes dicitonary"); //it prints this when I run
changes = [[NSDictionary alloc] init];
}
NSManagedObjectID* objectID = change.objectID;
NSMutableArray* changeArray = [changes objectForKey: objectID];
bool arrayDidNotExist = NO;
if (!changeArray){
changeArray = [[NSMutableArray alloc] init];
arrayDidNotExist = YES;
}
[changeArray addObject: [(this class's name) copyEventDictionary: change]]; //copies the NSManagedObject's attributes to an NSDictionary, assumedly works
if (arrayDidNotExist) [changes setObject: changeArray forKey: objectID];//throws the exception
//If I do the exact same line as above but do it to an [[NSMutableDictionary alloc] init] instead of the static dictionary changes, it does not throw an exception.
if (arrayDidNotExist) NSLog(#"New array created");
NSLog(#"changeArray count: %d", changeArray.count);
NSLog(#"changes dictionary count: %d", changes.count);
}
The exact exception message is this:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0xa788e30'
Use NSMutableDictionary instead of NSDictionary. You are getting exception as because , NSMutableDictionary can be modified dynamically, NSDictionary cannot. .
NSMutableDictionary is subclass of NSDictionary. So all methods of NSDictionary is accessible via NSMutableDictionary object. Moreover NSMutableDictionary also adds complementary methods to modify things dynamically, such as the method setObject:forKey:
EDIT
You have initialized it using NSDictionary instead of `NSMutableDictionary.
if (!changes){
NSLog(#"Making new changes dicitonary"); //it prints this when I run
//changes = [[NSDictionary alloc] init];
^^^^^^^^^^^^^^ ------------------> Change this.
changes = [[NSMutableDictionary alloc] init];
}
[__NSDictionaryI setObject:forKey:] shows that your dictionary is immutable. You are actually initializing your dictionary as immutable. That's why its raising exception on adding an object.
Here change this line:
if (!changes){
....
changes = [[NSDictionary alloc] init];
}
to:
if (!changes){
....
changes = [[NSMutableDictionary alloc] init];
}
You declared your dictionary to be of NSMutableDictionary, so at compile time your dictionary is of NSMutable dictionary, but at run time it is NSDictionary as you allocated it as NSDictionary, to which you can not make changes, hence the exception. Please define the dictionary as :-
changes = [[NSMutableDictionary alloc] init];
If you read the description of your exception, it says the same thing.
Hope this helps.

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: NSArrayM objectForKey

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM objectForKey:]: unrecognized selector sent to instance 0x12e654c0.
I am loading data on tableview from Array that has two dictionary objects. Dictionary object contains 2 nsstring object when ViewDidLoad called the code is below
while (sqlite3_step(statement) == SQLITE_ROW) {
NSString* delID = [NSString stringWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
NSString* name =[NSString stringWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
NSMutableDictionary *dict=[NSMutableDictionary dictionary];
[dict setObject:delID forKey:#"delID"];
[dict setObject:name forKey:#"name"];
[self.arr addObject:dict];
It never crash for first row but on second row indexPath.row==1 it always crash please see the screen shot below. Thanks for help
Here is I am filling self.arr again
-(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
if ([datePicker1.CurrentDate length]) {
UIButton *btn=(UIButton*)[self.view viewWithTag:btnTag];
[btn setTitle:datePicker1.CurrentDate forState:UIControlStateNormal];
}
if ([self.searchDel.arrSelectDelAdd count ])
{
[self.arr addObject:self.searchDel.arrSelectDelAdd];
[self.tblDelivery reloadData];
}
}
Remove the if condition from your code. As it is just adding first dictionary into the array not the second one.
//if (i==0){
[self.arr addObject:dict];
//}
Try this :)
Sorry to bother all of you Actually the problem is that I am adding second or another object like
[self.arr addObject:self.searchDel.arrSelectDelAdd]; //Incorrect, that is adding NSArray type not dictionary
then getting values in cellForRowAtIndexPath
NSDictionary *dict=[arr objectAtIndex:indexPath.row];//here dict will contain NSSArray type not dict type object its causing to crash app.
cell.lblID.text=(NSString*)[dict objectForKey:#"delID"];// at this line.
cell.lblName.text=(NSString*)[dict objectForKey:#"name"];
[self.arr addObjectsFromArray:self.searchDel.arrSelectDelAdd]; // correct, thats the solution giving contents of NSSArray and now working my code

App crash after '

My application is crashing when a ' appears in the title of the JSON code i'm parsing.
This line is loading the title's:
[[cell textLabel] setText:[item objectForKey:#"title"]];
JSON:
NSString *jsonString = [NSString
stringWithContentsOfURL:[NSURL URLWithString:#"**test.php"]
encoding:NSStringEncodingConversionAllowLossy
error:nil];
// Create parser
SBJSON *parser = [[SBJSON alloc] init];
NSDictionary *results = [parser objectWithString:jsonString error:nil];
parser = nil;
// Set tableData
[self setTableData:[results objectForKey:#"items"]];
Crash:
tableData NSArray * 0x00000001
2012-04-10 10:29:11.446 *[21222:f803] -[NSNull isEqualToString:]:
unrecognized selector sent to instance 0x146ace8 2012-04-10
10:29:11.447 *[21222:f803] * Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '-[NSNull
isEqualToString:]: unrecognized selector sent to instance 0x146ace8'
* First throw call stack: (0x13d4022 0x1565cd6 0x13d5cbd 0x133aed0 0x133acb2 0x15e0ff 0x2b10 0xb8c54 0xb93ce 0xa4cbd 0xb36f1 0x5cd21
0x13d5e42 0x1d8c679 0x1d96579 0x1d1b4f7 0x1d1d3f6 0x1db81ce 0x1db8003
0x13a8936 0x13a83d7 0x130b790 0x130ad84 0x130ac9b 0x12bd7d8 0x12bd88a
0x1e626 0x1ded 0x1d55) terminate called throwing an exception(lldb)
The key part of that crash info is: unrecognized selector sent to instance ... [NSNull isEqualToString:]
It looks like your JSON contains null somewhere that you are expecting a string. Later on, probably inside of setTableData: you will be doing something like this:
NSString* whatever = [items objectForKey:#"whatever"];
if([whatever isEqualToString:#"hello"]){
...
}
And that will crash, because the whatever variable contains NSNull, not an NSString like you were expecting.