Create multiple UITextFields programmatically using a for loop - objective-c

Brand new to coding; been utilizing stackoverflow religiously for months; first time asking a question; please be gentle.
I'm trying to create a series of UITextFields programmatically using a for loop. The fields should have names like "pax1name", "pax2name", "pax3name", etc.
The piece I'm missing is how to take a string and make it the name of a textField, changing the name of the textField each time the for-loop executes.
Here's my code, but maybe I'm going about this the wrong way? Thank you in advance!
// set up the names textfields
for (int i = 0; i < 7; i++) {
NSString *fieldName = [[NSString alloc] initWithFormat:#"pax%iname", (i + 1)];
// I can't figure out what goes here to create a UITextField with the name of fieldName
textField = [[UITextField alloc] initWithFrame:CGRectMake(15, (15 + (i * 40)), 400, 40)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.font = [UIFont systemFontOfSize:15.0];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
[namesViewController addSubview: textField];
[fieldName release];
[textField release];
}

Normally you use the UIView property tag for that. Use [textField setTag:<youCustomTag>] in your loop to set the value, e.g. your variable i. Please note that tag expect an NSUInteger and not an NSString.
To access the correct text field afterwards you'd call [[namesViewController view] viewWithTag:<yourCustomTag>].
BUT, is it really necessary to create multiple text fields for your view controller? There might be a more elegant solution by creating just one single text field and setting the tag-property on demand when the user taps a row. I don't know if that would work for you.

I think you've been going the wrong way about this. UITextField has no property called "name". To identify a control, you can use its tag property. See this code:
for (int i = 0; i < 7; i++) {
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(...)];
textField.tag = i + 1;
...
}

When you say the name of the textfield I'm presuming you mean the variable name rather than setting the text that is displayed. I.e. you want to create the variables in a loop, but later be able to reference them individually by name.
In that case, you can't do what you want to do. What you can do is stick them in an array for handy access later on.
NSMutableArray *paxNameFields = [[NSMutableArray alloc] init]; // before your loop
[paxNameFields addObject: textField]; // inside the loop
[paxNameFields objectAtIndex: 5]; //sometime later use the 6th field
Or if you just want to be able to identify which UITextField you're passed into a delegate callback later on, you can set/check the tag property.

UITextFields don't HAVE names. You're probably coming from HTML-world, where these things are basically a big hash of name-value pairs. Not like that in Cocoa Touch. As #Florian Mielke says, they each have an int .tag property, which is probably what you want to set.

Related

Creating a UIImageView using an NSString

I have to create a number of UIImageViews based on values stored in an NSString. The value that is stored will become the name for my UIImageView, each one will be created individually of course.
So to keep things simple my question is, can one create a UIImageView based on the value stored within an NSString?
Rough Example:
-(UIImageView)createMyFruitViews:(NSString *)fruit
{
NSString *fruit = #"";
UIImageView *fruitImage [fruit value]; //<-- made up for example purposes.
return fruitImage;
}
If this is not possible, could you please suggest a way around this?
FYI I've read through the forums too, the only thing that comes close is How to use NSSstring to instantiate a UIImageview; however I don't understand the answer and I am not sure that it can apply to what I need.
Try using UIImageView *fruitImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:fruit]];
I'm not quite sure I understood what you need... as far as I can tell, you have the name of an image on a NSString object, right?
Lets say you have an array of strings, each string representing the name of an image:
NSArray *myImageNames = [NSArray arrayWithObjects:#"image1.png", #"image2.png", #"image3.png", nil];
Then you'll create your imageViews using these images:
for (NSString *imageName in myImageNames) {
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
[self.view addSubview:myImageView];
[myImageView release]; // If you're not using ARC
}
If I didn't get exactly what you need, please let me know.

Label text not updating (cocos2d)

I have a class which I intend to reuse for a game with multiple levels and I'm having a problem with updating the label text. Basically, I'm trying to reuse this class for 15 levels of a game. So initially the value of the label is 1 then it should increase by one after the level has been cleared then the class is reloaded with the updated text. This is how I'm trying to update my label:
GameScene *stage= [stage node];
[[CCDirector sharedDirector]replaceScene:stage];
//stageNo is an integer that I pass to the label as it's text value. As long as its less that 15, it should go inside that code block.
if(stageNo < 15)
{
stageNo = stageNo + 1;
[stage.layer.stageLabel setString:[NSString stringWithFormat:#"%i", StageNo]];
}
This only works only once so if the default value of the label is 1, after the class is reloaded it becomes 2. After that, it's just stuck to 2. So my question is, how can I update the label text whenever the class is reloaded to increment by 1?
Seems like this is most definitely a scope problem. According to your comments you've done the right thing and created a property called stageLabel. The only problem is when you set it up initially you are not retaining it.
Instead of using
stageLabel = [CCLabelTTF labelWithString:[NSString stringWithFormat:#"%#", stageNo] fontName:#"Arial" fontSize:18];
you should use
self.stageLabel = [[CCLabelTTF alloc] initWithString:[NSString stringWithFormat:#"%#", stageNo] fontName:#"Arial" fontSize:18];
Separate the UILabel declaration from stringWithFormat in the init(). it then should work

The difference between how arrays are populated in ios?

Hello and Thanks to All,
Here is the situation, When I use the following methode to populate my array it works when I use Methode 2 it does not work. The objective is to change the color of text. Both Methods have been NSLOGED and the data is identical.
First way..(working name gets grayed out)
-cellForRowAtIndexPath
....
if ([self.secArray containsObject:indexPath]) {
cell.textLabel.textColor = [UIColor grayColor];
} .....
-didSelectRowAtIndexPath:
...
[secArray addObject:indexPath];
Second Way (not working - populate the Array from my .plist )
-cellForRowAtIndexPath
....
if ([self.secArray containsObject:indexPath]) {
cell.textLabel.textColor = [UIColor grayColor];
} .....
-viewWillAppear
NSString *filePathOrdersIndex = [self dataFilePathOrders];
NSMutableArray *chekDist;
chekDist = [[NSMutableArray alloc] initWithContentsOfFile:filePathOrdersIndex];
NSLog( #"data checkDist........... %#", chekDist);
if(!chekDist){
chekDist = [[NSMutableArray alloc]init];
}
for(id dist_data in chekDist){
secArray = [dist_data objectForKey:#"myIndexPath"];
//[secArray addObject:[dist_data objectForKey:#"myIndexPath"]];
}
both methods logged to console both arrays contain Identical array data....but second way is not working
any help is greatly appreciated.
In the second method, you are assigning an element of the checkDist array to the array itself, is each dist_data in checkDist a secArray?
From an outside perspective, these two methods are not functionally equivalent without knowing more information about what kinds of data these variables hold. Though since you are setting the secArray variable each time the for loop executes, I'm assuming this is incorrect and you need to use the line you had commented-out in your second method ([secArray addObject:[dist_data objectForKey:#"myIndexPath"]];).
If after using that line instead it is still not working, verify that secArray has been created (make sure it's not nil) when the second method executes.

NSMutableArray objectatindex always shows the last Object

my problem is that my NSMutableArray always get the last element with the objectatindex-method.
I have an array with some classes derived from UIViewController. I want to show one View after another.
first i fill the array:
ContactViewController *ContactView = [[ContactViewController alloc]init];
QuestionViewController *QuesView = [[QuestionViewController alloc]init];;
ContactView.mydelegate = self;
[QuesView setDelegate:self];
[Views addObject:ContactView];
Views =[[NSMutableArray alloc]initWithCapacity:11];
for (int i = 0; i < 11; i++) {
[QuesView setParam:#"text" :i ];
[Views addObject:QuesView];
}
after that i want to get the actual view and jump to the next like that:
-(IBAction)Button:(id)sender
{
UIViewController *newView = [[UIViewController alloc]init];
newView = (UIViewController*)[Views objectAtIndex:enumerator];
[self presentViewController:newView animated:YES completion: nil];
enumerator++;
//dismiss old view here....
NSLog(#"number %d",[newView getNumber]);
}
the new view is not shown and the number in the log is always the last number of the array. I tried to go with a for loop through all element in "Views" but there is always the last number in every object....
any hints?
You probably want to create multiple QuestionViewController instances. But you actually create only one object and call setParam on it 11 times.
Also this line [Views addObject:ContactView] has no effect, because you create a new array object and assign it to Views in the next line. The same thing with UIViewController *newView = [[UIViewController alloc]init]. Hope you are using ARC, otherwise this would create a memory leak!

Objective-C: Image Management between classes

I am trying to create a model with multiple images in a factory model style. I have one class that handles the individuals, one class that handles the group of individuals and a ViewController.
testImage = [[UIImageView alloc] initWithFrame:CGRectMake(250, 500, 30, 30)];
testImage.image = [UIImage imageNamed:#"myImage.png"];
testImage.animationDuration = 1.5;
testImage.contentMode = UIViewContentModeCenter;
[self.view addSubview:testImage];
http://jcdeveloperworld.blogspot.com/2009/07/iphone-game-tutorial-part-1.html -- Thanks
That code works when it is just in the viewController, and now I am trying to make the individuals keep track of their own image. So i put the
testImage = [[UIImageView alloc] initWithFrame:CGRectMake(250, 500, 30, 30)];
testImage.image = [UIImage imageNamed:#"myImage.png"];
testImage.animationDuration = 1.5;
testImage.contentMode = UIViewContentModeCenter;
[self.view addSubview:testImage];
in a separate class and then tried to display it from my viewController. It is my understanding that I can't just tell the viewController to display something from a separate class.
flock *newFlock = [[flock alloc] init];
[newFlock makeFlock];
NSMutableArray *tempFlock = [[NSMutableArray alloc] init];
tempFlock = newFlock.theFlock;
individualsClass *tempIndividual = [[individualsClass alloc] init];
tempIndividual = [tempFlock objectAtIndex:0];
UIImageView *tempImage = [[UIImageView alloc] initWithFrame:CGRectMake(250, 500, 30, 30)];
tempImage = tempIndividual.individualImage;
[self.view addSubview:tempImage];
I also tried it without all the copying, but the dot notation started to get in the way because I'm accessing properties of objects in an NSMutableArray (which seems absurdly difficult in objective C). I could use some help in figuring that out too
ie.
flock.[theFlock.individualImage.image objectAtIndex:1] //Doesn't work
I am kind of new to objective C, so perhaps I'm attacking this problem wrong. This is being done for an iPad app
It's not clear what you're trying to do, but you're definitely doing a lot of stuff you don't need to. Consider these lines of your code:
NSMutableArray *tempFlock = [[NSMutableArray alloc] init];
tempFlock = newFlock.theFlock;
The first line declares a variable named tempFlock of type NSMutableArray *. Then it creates and initializes an empty NSMutableArray and assigns it to tempFlock. The second line then assigns newFlock.theFlock to tempFlock, overwriting the only reference to the array you created in the first line. You can just say this:
NSMutableArray *tempFlock = newFlock.theFlock;
Anyway, the correct syntax for your last block is this:
[flock.theFlock objectAtIndex:1].individualImage.image
So maybe this is what you want to do:
[self.view addSubview:[flock.theFlock objectAtIndex:1].individualImage];
Also, flock and individualsClass are not good class names in Objective-C. Flock and Individual might be better names.
And it's confusing that flock instances have a property named theFlock. It looks like theFlock is just an array of individuals, so a better name for the property would probably be individuals.
If all the "dot" syntax is causing problems with understanding just don't use them, they are just an alternate syntax for method invocation.
[myInstance value] is the same as myInstance.value, which can be viewed as a simple substitution.
Also avoiding long compound statements can help understanding, instead use one or more intermediate well named variables. Trust the compiler to optimize them.
So, as #rob writes:
[flock.theFlock objectAtIndex:1].individualImage.image
the equivalent could be:
[[[[flock theFlock] objectAtIndex:1] individualImage] image]
Broken into multiple statements:
tempFlock = [[flock theFlock] objectAtIndex:1];
tempIndividual = [tempFlock individualImage];
image = [tempIndividual image];