Convert a string + a number to an onject - iphone

I am new to Obj C, but familiar with OOP. I am working on a game that uses collision detection to score points and change UIImageView properties like background color.
I have a finite number of UIImageViews that are subviews of a larger view. I can manually check for collision and set the background colors of the UIImageViews accordingly. The problem is that this creates a rather large if / else block that I can see growing out of control. In JavaScript I can use a for loop and eval() to evaluate a string + i (the loop var) and then simply call the new var.backgroundColor = someColor;
It seems that eval is not used in OBJ C, so I am looking for an equivalent that will allow me to create a loop that executes the same block of code on a given object that only differs from other objects by name only:
Example:
if (someStatement == true){
object_01.someProperty = newProperty;
} else if (someOtherStatement == true){
object_02.someProperty = newProperty;
} else if (someOtherOtherStatement == true){
object_03.someProperty = newProperty;
}
I want to write the above as a loop. I realize I can use an Array, but if so, how? Also, I want to loop through CGRects which are not storing properly in an Array.
Any help greatly appreciated!
Damon

Creating your array:
NSMutableArray *items = [NSMutableArray array];
Populating your array with CGRects:
[items addObject:[NSValue valueWithCGRect:frame]];
Pulling a CGRect from the array:
CGRect frame = [[items objectAtIndex:0] CGRectValue];
Replacing an index in the array:
[items replaceObjectAtIndex:0 withObject:[NSValue valueWithCGRect:frame]];

The best way is to put object_01, object_02, ... into an array and then use `-[NSArray objectAtIndex:] to access the objects.
You could also use Key-Value Coding:
NSString *keyPath = [NSString stringWithFormat:#"object_0%d.someProperty", objectIndex];
[self setValue:newProperty forKeyPath:keyPath];
But as rpetrich mentioned, it's not good programming style.

Related

Sorting IBOutletCollection Array of TextFields According to frame.origin.y

I'm trying to sort array of textFields according to frame.origin.y. But when I ran simulator it got stuck. Any Idea?
IBOutletCollection(UITextField) NSArray *textFields
My code :
-(NSMutableArray *)bubbleSort:(NSMutableArray *) unsortedArray{
NSInteger i,j;
//NSLog(#"%#",unsortedArray);
for(i=0;i<unsortedArray.count;i++)
{
for(j=0;j<i;j++)
{
if(((UITextField *)[unsortedArray objectAtIndex:i]).frame.origin.y > ((UITextField *)[unsortedArray objectAtIndex:j]).frame.origin.y)
{
UITextField *temp=[unsortedArray objectAtIndex:i];
[unsortedArray insertObject:[unsortedArray objectAtIndex:j] atIndex:i];
[unsortedArray insertObject:temp atIndex:j];
}
}
}
//NSLog(#"%#",unsortedArray);
return unsortedArray;
}
Like Learner said, you just keep on inserting object in your array, so you never leave your outer for loop. To swap two elements, you can use
- (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2
so in your case, inside your if, you can simply write
[unsortedArray exchangeObjectAtIndex:i withObjectAtIndex:j];
Reference
look like this will keep on inserting object in array. so unsortedArray.count will keep increasing. in my opinion you need to remove object first and than insert it to upper rank or lower rank depending on algorithm.
se documentation for NSMutableArray insert object function.
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html

Correctly removing objects from view and array?

In my "connect4" style game I have an array representing a 7x6 grid, each "cell" in the array contains either NSNull or a UIView subclass 'CoinView'. Is the following the correct way to remove objects from the NSMutableArray and the primary view?
- (IBAction)debugOrigin:(id)sender {
int x = 0;
int y = 0;
//get the coin object form the grid
CoinView *coin = [[grid objectAtIndex:x] objectAtIndex:y];
//cancel if there's no coin there
if ([coin isKindOfClass:[NSNull class]]) { return; }
//remove the coin from memory
[coin removeFromSuperview];
coin = nil;
[[grid objectAtIndex:x] setObject:[NSNull null] atIndex:y]; //will this leak?
}
Thanks!
Your code will not leak, and is in fact (almost) correct.
You should remove this comment, as you're not dealing with memory in your code (and it may end up confusing you as to what the code really does):
//remove the coin from memory
In the following line you're removing the view referenced by local variable "coin" from its superview:
[coin removeFromSuperview];
And you assign nil to your local variable coin, which is good practice to make sure it's not being used later in the code:
coin = nil;
As far as I know there is no setObject:AtIndex: for NSMutableArray. Use replaceObjectAtIndex:withObject: instead:
[[grid objectAtIndex:x] replaceObjectAtIndex:y withObject:[NSNull null]]; //will this leak?
As a last note, I recommend that you read up a bit on memory management and memory leaks (from Apple's developers documentation). The first offers you some hints and tips that make memory management much easier to understand.

Trying to Concatenate Object names in Objective-C

I know I can concatenate a variable name using stringwithformat, but is it possible to concatenate an object name? I'm not having any luck working around this one.
image+1.hidden = YES; for example.
If I wanted to loop through that, say 10 times, how would I create the 'image+1' part?
Thanks for any help.
I don't think that it is possible to concatenate object names in objective c, but you could create an array of images, and then reference each image like
image[0].hidden = YES;
That would fit the for loop. You could also add the images (I assume that they are UIImages) to an NSArray, then loop through like so:
NSArray* arrayOfImages;
for(UIImage* image in arrayOfImages)
{
image.hidden = YES;
}
Add the objects to an NSArray or NSMutableArray. Then loop through the array to set each object's properties.
For the purposes of discussion mainly, you can use key-value coding to set a property by its name. So, supposing you had instance, an instance of a class that provides the properties image1, image2 and image3 then you could perform:
for(int x = 1; x < 4; x++)
{
// produce the name of the property as an NSString
NSString *propertyName = [NSString stringWithFormat:#"image%d", x];
// use key-value coding to set the property
[instance setValue:someValue forKey:propertyName];
}
For the full list of accessor methods that compliant classes export, see the NSKeyValueCoding Protocol Reference. NSObject implements NSKeyValueCoding, and all properties declared as #property and implemented as #synthesize are compliant, as are any other properties with suitable accessors.
As already noted in the other answers, when what you want is an ordered list of objects so that you can do something with each in turn, either a C-style array or an NSArray is the correct way to proceed, with an NSArray being preferred for style reasons.
NSArray *array = [[NSArray alloc] initWithObjects:image1, image2, image3, image4, image5, image6, image7, image8, image9, image10, nil]; // or use NSMutableArray
for (int x = 0; x < 10; x++) {
((UIImage*)[array objectAtIndex:x]).hidden = YES;
}

How can I modify a CGRect stored as NSValue in an NSArray?

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

Adding UIImageView to an NSMutableDictionary

I'm trying to add multiple instances of UIImageView(s) to an NSMutableArray of NSMutableDictionar(ies).
I am doing this, to be able to go back and pull out the UIImageView reference, to change the position of these images.
It seems that, when I pull the info out of the Dictionary, that it only returns a null pointer...
Any suggestions on how I should implement this? There may be a way easier method to store a list of n images and be able to reference them later....
// (for i = 0 to 30)
UIImageView *newBall = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"ball.png"]];
newBall.center = CGPointMake (arc4random() % 280 + 20, arc4random() % 440 + 20);
[self.view addSubview:newBall];
NSMutableDictionary *dictBall = [[[NSMutableDictionary alloc] init] autorelease];
[dictBall setValue:newBall forKey:#"imgBall"];
// the dictionary is then added to the array
[newBall release];
// end for loop
(I'm using a Dictionary, because I also store a dy/dx value for rate of change in movement)
Code above doesn't look OK to me.
You're creating a new NSMutableDictionary *dictBall everytime through the loop. Is something retaining it after the loop exists? Doesn't look like it from your code. This may be why your object is nil.
Move this line outside/before the for loop, and you should be fine.
Also, are you sure you want to store UIViewImage in a dictionary? Why not just an ID (based on the tag) and the coordinates (CGPoint or CGRect)? This way you can use the tag to find the UIimageView via the tag and move it where ever you want? Less expensive memory wise.