out of range in objectAtIndex objective c - objective-c

The count of children_ (CCArray) outputs 15 and I'm receiving error:
'NSInternalInconsistencyException', reason: 'index out of range in objectAtIndex(14), index 15'
for (NSInteger i=[children_ count]-1; i>=0; i++) {
CCNode *c = [children_ objectAtIndex:i];
if ([c isKindOfClass:[CCLabelTTF class]]) {
[c removeFromParentAndCleanup:YES];
}
}
How would I solve this? Trying to remove all the labels in order to change their string value.
On my CCLayer I have have also some CCMenuItemLabel and CCMenuItemLabelAndSprite...

It looks like you want to iterate backwards through the collection class, so you need to perform i-- to modify the index variable:
for (NSInteger i=[children_ count]-1; i>=0; i--) {
CCNode *c = [children_ objectAtIndex:i];
if ([c isKindOfClass:[CCLabelTTF class]]) {
[c removeFromParentAndCleanup:YES];
}
}

you should use fast enumerating if possible:
for (id obj in [childres_ reverseObjectEnumerator]){
if ([obj isKindOfClass:[CCLabelTTF class]]) {
[obj removeFromParentAndCleanup:YES];
}
}
or with the block syntax
[children_ enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop){
if ([obj isKindOfClass:[CCLabelTTF class]]) {
[obj removeFromParentAndCleanup:YES];
stop= YES;
};
}];

It seems that you are initializing your for loop counter with count-1 and incrementing, so the first value of i would be 14 , and the next one 15 (out of range)
Try this :
for (NSInteger i=0; i<[children_ count]; i++) {
}

Related

Using enumerateObjectsAtIndexes or a for-loop to iterate through all indexes of an NSArray BEFORE a given index

What's the most concise way to iterate through the indexes of an NSArray that occur before a given index? For example:
NSArray *myArray = #[ #"animal" , #"vegetable" , #"mineral" , #"piano" ];
[myArray enumerateObjectsAtIndexes:#"all before index 2" options:nil
usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
// this block will be peformed on #"animal" and #"vegetable"
}];
Also, this should not loop at all if the given index is 0.
What's the most concise, elegant way to do this? So far I've only cobbled together clumsy multi-line answers that use annoying NSRanges and index sets. Is there a better way I'm overlooking?
NSArray *myArray = #[ #"animal" , #"vegetable" , #"mineral" , #"piano" ];
NSUInteger stopIndex = 2;
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx == stopIndex) {
*stop = YES; // stop enumeration
} else {
// Do something ...
NSLog(#"%#", obj);
}
}];
[myArray enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, idx)]
options:0
usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
}];
What about :
index = 2;
for (int i = 0; i < [myArray count] && i < index; ++i) {
id currObj = [myArray objectAtIndex:i];
// Do your stuff on currObj;
}
Personally I'd go with a block-based enumeration as shown by Martin R or yourfriendzak, the accepted answer by giorashc is probably the worst, as it doesn't provide a mutation guard.
I want to add a (correct) fast enumeration example
NSUInteger stopIndex = 2;
NSUInteger currentIndex = 0;
for (MyClass *obj in objArray) {
if (currentIndex < stopIndex) {
// do sth...
} else {
break;
}
++currentIndex;
}

NSMutableArray to NSString conversion

Here is the string from NSMutableArray:
(
(
"Some String Value"
)
)
This code displays the string value that I want, but however, it displays with the brackets and quotes. How do I remove them?
Thank you in advance!!
In your case it is 2D Array:
Something like this:
NSArray *arr=[NSArray arrayWithObject:#"asdf"];
NSArray *arr2=[NSArray arrayWithObjects:arr, nil];
You need to go to 2nd level to retrive it as :
NSLog(#"=> %#",arr2[0][0]);
NSString *string=arr2[0][0];
-(void)repeatArray:(NSArray *)array1
{
static NSMutableString *InsideString; // Better to use global Varaible declared in ViewDidLoad/loadView
NSArray *array = array1; //Its your array
for (int i = 0; i< [array count]; i++) {
if ([[array objectAtIndex:i] isKindOfClass:[NSArray class]]) {
[self repeatArray:[array objectAtIndex:i]];
} else if ([[array objectAtIndex:i] isKindOfClass:[NSString class]]) {
[InsideString appendString:[NSString stringWithFormat:#"%# ", [array objectAtIndex:i]]];
}
}
}

Get the correct index of dictionary

NSMutableArray *tmpMutArr = [NSMutableArray arrayWithArray:allObjectsArray];
NSLog(#"The content of array is%#",tmpMutArr);
int index;
for (int i=0;i<[tmpMutArr count];i++)
{
if([[tmpMutArr objectAtIndex:i] isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *tempDict = [tmpMutArr objectAtIndex:i];
if([[tempDict valueForKey:#"Name"] isEqualToString:[NSString stringWithFormat:#"%#", nameString]])
{
index = i;
}
}
}
[tmpMutArr replaceObjectAtIndex:index withObject:[NSDictionary dictionaryWithDictionary:mutDict]];
This code is not replacing the matching object in tmpMutArr as I want it to, but replaces all objects in tmpMutArr instead. How to replace only the index I want?
I know that tmpMutArr containing all objects before the replacement, so I just need to specify the index correctly I think. How to do so?
NSMutableArray *tmpMutArr = [NSMutableArray arrayWithArray:allObjectsArray];
NSLog(#"The content of array is%#",tmpMutArr);
int index;
for (int i=0;i<[tmpMutArr count];i++)
{
if([[tmpMutArr objectAtIndex:i] isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *tempDict = [tmpMutArr objectAtIndex:i];
if([[tempDict valueForKey:#"Name"] isEqualToString:nameString])
{
index = i;
break; // << added break
}
}
}
[tmpMutArr replaceObjectAtIndex:index withObject:[NSDictionary dictionaryWithDictionary:mutDict]];
maybe, you should try to this version... you have not specified which index is needed, I suppose the first one.
for (int i=0;i<[tmpMutArr count];i++) {
if([[tmpMutArr objectAtIndex:i] isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *tempDict = [tmpMutArr objectAtIndex:i];
if([[tempDict valueForKey:#"Name"] isEqualToString:[NSString stringWithFormat:#"%#", nameString]]) {
index = i;
break; // when you find the first one, you should go out from the iteration
}
}
}

NSPredicate instead of loop to filter an array of objects

I have been told that I can use NSPredicate to duplicate the results of this method
- (void) clearArrayOut
{
bool goAgain = false;
for (int j=0; j<[array count]; j++)
{
if ([[array objectAtIndex:j] someMethod] == NO)
{
[array removeObjectAtIndex:j];
goAgain = true;
break;
}
}
if (goAgain) [self clearArrayOut];
}
How can I make an NSPredicate that will filter an array based on the results of some method of a custom class's call?
To make a copy with the filter applied:
NSArray *filteredArray = [someArray filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^(id object, NSDictionary *bindings) {
return [object someMethod]; // if someMethod returns YES, the object is kept
}]];
To filter an NSMutableArray in place:
[someMutableArray filterUsingPredicate:
[NSPredicate predicateWithBlock:^(id object, NSDictionary *bindings) {
return [object someMethod]; // if someMethod returns YES, the object is kept
}]];
But I would probably just use a for loop if I were filtering a small array. However, I'd write my for loop a little differently to avoid having to either decrement the index variable or call myself recursively:
- (void)clearArrayOut:(NSMutableArray *)array {
for (int i = array.count - 1; i >= 0; --i) {
if (![[array objectAtIndex:i] someMethod]) {
[array removeObjectAtIndex:i];
}
}
}
You simply write it into your predicate, for example, lets assume you have an object with a method called isOdd and you want to filter your array to include only objects that return true for isOdd, you can do this:
#import <Foundation/Foundation.h>
#interface barfoo : NSObject
{
int number;
}
- (BOOL)isOdd;
- (id)initWithNumber:(int)number;
#end
#implementation barfoo
- (NSString *)description
{
return [NSString stringWithFormat:#"%i", number];
}
- (BOOL)isOdd
{
return (number % 2);
}
- (id)initWithNumber:(int)tnumber
{
if((self = [super init]))
{
number = tnumber;
}
return self;
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
NSMutableArray *array = [NSMutableArray array];
for(int i=0; i<10; i++)
{
barfoo *foo = [[barfoo alloc] initWithNumber:i];
[array addObject:[foo autorelease]];
}
NSLog(#"%#", array); // prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isOdd == true"]; // This is oure predicate. isOdd must be true for objects to pass
NSArray *result = [array filteredArrayUsingPredicate:predicate];
NSLog(#"%#", result);
}
}
Of course this also works the other way around, your predicate could also read isOdd == false or you can add even more requirements for an object to pass. Eg isOdd == true AND foo == bar. You can read more about the NSPredicate syntax in the NSPredicate documentation.
Your implementation is terribly inefficient to start with: rather than continuing the deletions recursively, you could change your loop to not advance if an object has been deleted, like this:
- (void) clearArrayOut {
int j = 0;
while (j < [array count]) {
if ([[array objectAtIndex:j] someMethod] == NO) {
[array removeObjectAtIndex:j];
} else {
j++;
}
}
}
You could do the same thing using filterUsingPredicate:, like this:
- (void) clearArrayOut {
NSPredicate *p = [NSPredicate predicateWithBlock:^BOOL(id obj, NSDictionary *bindings) {
return [obj someMethod] == NO
}];
[array filterUsingPredicate:p];
}

Obj-C, function to return index of nsstring found in nsarray?

I've been looking to see if I can find a function like indexOf.
I have an array.
self.data = [[NSArray alloc] initWithObjects:#"apple", #"lemon", #"pear", nil];
Looking for a function to return which would look for lemon and return 1 ?
how about indexOfObject:?
NSUInteger index = [self.data indexOfObject:#"lemon"];
Try this method.
-(int)indexOfString:(NSString *)string inArray:(NSArray *)array {
for(int i=0; i<[array count]; i++) {
if ([[array objectAtIndex:i] class] == [NSString class]) {
if ([[array objectAtIndex:i] isEqualToString:string]) {
return i;
}
}
}
}
EDIT: The other answer using -indexOfObject: is better.