views:

488

answers:

2

Hello,

I am creating an NSArray with CGRects using the following line:

[self setMyArray:[NSArray arrayWithObjects:[NSValue valueWithCGRect:CGRectMake(x,y,z,a)], [NSValue valueWithCGRect:CGRectMake(x,y,z,a)], nil]]

I am then trying to update the CGrects in the Array every so often like this:

for (NSValue *bound in myArray)
  {
   CGRect myRect = [bound CGRectValue];
   myRect.origin.y += 2;
  }

However this is not working, when the loop runs again, the origin is still the same. I am assuming this has something to do with the NSValue wrapper?, What can I do so the value is actually updated in the array?. Thank you.

-Oscar

+2  A: 

NSValue objects are immutable so there is nothing you can do. You should use a mutable array and replace the existing object with a new NSValue instance containing the new rect.

Ole Begemann
I guess I will have to do that, although is there much overhead if I am removing and replacing objects in an NSMutableArray quite often?, that can be up to every .02 seconds.
OscarMk
Replacing an object in a mutable array should be very fast since it's only a matter of moving pointers around. Allocating the new NSValue instance would probably be a harder hit on performance, but I wouldn't worry about it. 50 allocations per second is actually not very much. You shouldn't try to optimize code before you are certain that it is a bottleneck.
Ole Begemann
+3  A: 

As others mentioned, NSValue instances are not mutable so you will have to recreate them and then replace them in an NSMutableArray.

Another option is to use more 'classic' C memory management (malloc/free) and manage your array that way. There is nothing wrong with going that route. You just have to be more careful as it is not has high level as the Objective-C/Foundation APIs.

// Create an array to hold 100 rectangles
CGRect* rectangles = (CGRect*) malloc(100 * sizeof(CGRect));

// Change the rectangle at index 2 (remember arrays are 0 based, so this is the 3rd)
CGRect* rect = &rectangles[2];
rect->size.width /= 2.0;

// Shortcut for accessing rectangles
rectangles[2].size.width = 100.0;

// Get rid of the array
free(rectangles);

Might be faster too if you work on for example a game.

St3fan
Thank you I will try this option and yes I am working on a game.
OscarMk