简体   繁体   中英

populate NSMutableArray with data from for loop

I'm trying to execute what seems like simple code related to NSMutableArray and I've hit a wall. Here's my code:

NSMutableArray *newArray = [[[NSMutableArray alloc] initWithCapacity:4] retain];
NSArray *existingSection2 = [[NSArray alloc] initWithObjects:@"S2 Item1",@"S2 Item2",@"S2 Item3",@"S2 Item4",nil];

for (int i=0; i<[existingSection2 count]; i++) {
    NSString *val = [[NSString alloc] initWithString:[existingSection2 objectAtIndex:i]];
    [newArray addObject:val];
    NSLog(@"val %i is %@ new array now contains: %@",i,val,[newArray objectAtIndex:i]);
    NSLog(@"new array description: ",[newArray description]);
}
NSLog(@"what's in newArray: ",[newArray objectAtIndex:0]);

As I understand it, here's what I'm doing:
1) Allocate a new NSMutableArray called newArray with a capacity of 4
2) Allocate an NSArray called existingSection2 with four NSString values
3) Iterate through each of the four NSStrings in existingSection2
3a) Allocate an NSString called val with the contents of the existingSection2 array at position i
3b) Add val to newArray in the next available position
3c) Log some stuff for debugging
4) Log the final contents of newArray for debugging

This code is in application:didFinishLaunchingWithOptions: but here's what my console window shows when I launch in the Simulator:

2011-06-26 15:50:48.203 ArrayTest[14936:207] val 0 is S2 Item1 new array now contains: S2 Item1
2011-06-26 15:50:48.205 ArrayTest[14936:207] new array description: 
2011-06-26 15:50:48.205 ArrayTest[14936:207] val 1 is S2 Item2 new array now contains: S2 Item2
2011-06-26 15:50:48.205 ArrayTest[14936:207] new array description: 
2011-06-26 15:50:48.206 ArrayTest[14936:207] val 2 is S2 Item3 new array now contains: S2 Item3
2011-06-26 15:50:48.206 ArrayTest[14936:207] new array description: 
2011-06-26 15:50:48.206 ArrayTest[14936:207] val 3 is S2 Item4 new array now contains: S2 Item4
2011-06-26 15:50:48.206 ArrayTest[14936:207] new array description: 
2011-06-26 15:50:48.207 ArrayTest[14936:207] what's in newArray: 

I don't understand why I'm not filling up newArray with those four new NSString objects! I've been searching SO for similar questions, but the answers all seem to be related to not initializing an NSMutableArray which I believe that I'm doing correctly.

Thanks for any help!

You have a few problems which I'd like to point out, and I hope you can learn something from them. Here we go...

Memory management

When you create an object using alloc , new , or copy , such as [[NSArray alloc] ...] or [[NSString alloc] ...] , it is returned with a +1 retained count. This means you "own" the object and are responsible for releasing it later by calling release (which you're not currently doing in your code). If you use, for example, [NSArray arrayWith...] , then you don't get a +1 retain count (you get an autoreleased object), and if you want it to stick around you have to call retain .

That said, when you do

NSMutableArray *newArray = [[[NSMutableArray alloc] initWithCapacity:4] retain];

The alloc gives you a +1 retain count, and then you're calling retain a second time! This is unnecessary.

However, since you don't need to use your arrays or strings outside this function, you don't need to retain them at all, so you can just use:

NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:4];

and

NSString *val = [NSString stringWithString:[existingSection2 objectAtIndex:i]];
// or even more simply
NSString *val = [existingSection2 objectAtIndex:i];

For more details and best practices, please read the Memory Management Programming Guide .

Loops/iteration

Your method of using [existingSection2 count] and i++ in a for loop works, but isn't the best way to do things. Obj-C has what's called Fast Enumeration , which is a lot simpler and I hope you'll use it:

for (NSString *val in existingSection2) {
    //...
}

NSLog and format strings

The NSLog function works (similar to C's printf ) by taking a format string (which contains format specifiers like %d for integers and %@ for Obj-C objects), and then a list of arguments to put in for the specifiers.

When you use

NSLog(@"new array description: ",[newArray description]);

you will only log the string "new array description: " because you don't have a format specifier corresponding to the description. Instead you should do:

NSLog(@"new array description: %@", [newArray description]);
// or even more simply
NSLog(@"new array description: %@", newArray);

There's also more information available on the String Format Specifiers that you can use with NSLog.

Overall

Here's a rewrite of your code using the techniques I described above.

NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:4];
NSArray *existingSection2 = [NSArray arrayWithObjects:@"S2 Item1",@"S2 Item2",@"S2 Item3",@"S2 Item4",nil];

for (NSString *val in existingSection2) {
    [newArray addObject:val];
    NSLog(@"value is %@",val);
    NSLog(@"new array contains: %@", newArray);
}
NSLog(@"what's in newArray: %@",[newArray objectAtIndex:0]);

You need to add an %@ in your format string when printing the array description.

Also, you don't need to explicitly call description because it gets called automatically when printing an object with %@ , as in:

NSLog(@"New array is: %@", newArray);

you have a logging problem:

NSLog(@"new array description: ",[newArray description]);

should be

NSLog(@"new array description: %@",[newArray description]);

bonus help:

NSMutableArray *newArray = [[NSMutableArray alloc] initWithCapacity:4];  // fix memory leak
NSArray *existingSection2 = [[NSArray alloc] initWithObjects:@"S2 Item1",@"S2 Item2",@"S2 Item3",@"S2 Item4",nil];

for (id section in existingSection2) // fast enumeration
{
    NSString *val = [[NSString alloc] initWithString:[existingSection2 objectAtIndex:i]];
    [newArray addObject:val];
    NSLog(@"val %i is %@ new array now contains: %@",i,val,[newArray objectAtIndex:i]);
    NSLog(@"new array description: %@",[newArray description]);
    [val release]; // fix memory leak
}

NSLog(@"what's in newArray: %@",[newArray objectAtIndex:0]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM