Search code examples
objective-cnsarrayuncaught-exception

"unrecognized selector sent to instance" for NSArrayI


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

Solution

  • 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.)