views:

54

answers:

1

I have the following code which is producing this error. I cannot understand why the subarrayWithRange message is being sent to a string? When it is clearly an array?

static const int kItemsPerView = 20;
NSRange rangeForView = NSMakeRange( page * kItemsPerView, kItemsPerView );

NSMutableArray *temp = [[APP_DELEGATE keysArray] mutableCopyWithZone:NULL]; 
NSArray *itemsForView = [temp subarrayWithRange:rangeForView];

for (int loopCounter = 0;loopCounter < r*c;loopCounter++){
    NSLog(@"%i: %@ ", loopCounter, [itemsForView objectAtIndex:loopCounter]);
}

Error:

-[NSCFString subarrayWithRange:]: unrecognized selector sent to instance 0x6b071a0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: [NSCFString subarrayWithRange:]:

Thanks

+3  A: 

These kinds of errors are usually memory-management-related. Essentially, you're sending a message to an address that's now occupied by some other object because the previous occupant has unexpectedly disappeared. Since that address space could be occupied by anything, you just happen to be asking an NSCFString something to which it doesn't respond.

If you pause the debugger right after you create the temp array, what do you see assigned to temp? I'm guessing something's not quite right with whatever -keysArray returns. You might want to double-check how the memory is handled in whatever that's supposed to return. By the name, I suppose your app delegate has an array called "keysArray" as an instance variable. Perhaps that's not being properly retained when it's created or assigned?

Joshua Nozzi
After creation, `temp` is an array of 80 strings, debug tooltip only shows 10 items though Not sure if that is just Xcode or not? You are correct keysArray is an instance variable in my App Delegate, a property defined as (nonatomic, retain) and then synthesized and assigned using a convenience method `arrayWithContentsOfFile`. I don't need to retain it manually do I?
joec
Yes. You didn't create it, the convenience method did. Therefore, if you want it to stick around after it's created, you need to stake a claim by retaining (or create a copy of your own). Take another look at the memory management rules.
Joshua Nozzi
If you use the property accessor instead of assigning, then you won't need the retain; or, you can call `[[NSArray alloc] initWithContentsOfFile:@"somepath"]` instead.
jlehr
True, but I think it's important to know what's going on behind the conveniences Objective-C 2 brings (@property, @synthesize, etc.). In fact, to make effective use of @property declarations in a non-garbage-collected environment you need to know just as much about Cocoa memory management.
Joshua Nozzi