iPhone OS: Using an NSString variable to specify a property or ivar - iphone

I have a program that I want to either hide or show certain UIbuttons depending on certain variables and all the buttons are named incrementally like 'button1, button2, button3.'
So I want to iterate through the buttons but I don't know how to address the button in an assignment statement using an nsstring as a variable inside a dot notation assignment, such as:
for (int i = 1; i < weekday; i++) {
int buttonIncrement = 0;
NSString *tempString = [[NSString alloc] initWithFormat:
#"calbutton%i", buttonIncrement];
self.tempString.hidden = YES;
}
The "tempString" part of the assignment I want to tell it to insert "calbuttonx" where x is the button number.
Can you do this somehow? if so please explain.

Use an array!
If you can't use an array, you can reference to a property by string with Key-Value Coding (KVC):
UIButton* button = [self valueForKey:tempString];
button.hidden = YES;

You can also assign a tag to each button in IB and get the button associated with the tag using
- (UIView *)viewWithTag:(NSInteger)tag
as defined on class UIView, for example:
for( int k = 0; k < 5; ++k ) {
id subview = [self.view viewWithTag: k];
if( subview ) {
...
}
}

Related

How can I increase numeric part of property name in for() loop?

I've 10 pan recognisers and want to assign to class property.
How can I increase numeric part of property name in for() loop?
for (int i=0; i < [_myArray count]; i++)
{
myClassInstance.recognizer = pangesture + i ?? // doesn't work of course. but how??
}
It's not fantastic form — definitely follow Caleb's comments wherever possible — but if you're really backed into a corner:
for(int i = 0; i < [_myArray count]; i++)
{
NSString *nameOfProperty = [NSString stringWithFormat:#"pangesture%d", i];
UIPanGestureRecognizer *recogniser = [self valueForKey:nameOfProperty];
}
That's using key-value coding; IBOutlets are necessarily KVC compliant or there'd be no way to load the NIB.
I've 10 pan recognisers and want to assign to class property. How can
I increase numeric part of property name in for() loop?
I'm not sure I understand your question fully, but assuming that you've got 10 gesture recognizers named g1 through g10 that you want to assign to 10 objects using a loop, a good approach would be to put those 10 gesture recognizers into an array and then make the assignment using the current index:
NSArray *recognizers = #[g1, g2, g3, g4, g5, g6, g7, g8, g9, g10];
if ([recognizers count < [_myArray count]) {
NSLog("Houston, we have a problem! Not enough gesture recognizers to go around.");
}
for (int i=0; i < [_myArray count]; i++)
{
myClassInstance.recognizer = recognizers[i]; // note the fancy "new" array access syntax!
}
If you're not allocating the gesture recognizers individually, then you can just create one each time though the loop:
for (MyClass *instance in _myArray) {
instance.recognizer = [[UIGestureRecognizer alloc] init...];
}

How can I read UITextField value in an IBAction. I'm creating UITextField programmatically

How can I read UITextField value in an IBAction? I'm creating UITextField programmatically. So I can't set #property and #synthesize using Xcode. The code to generate UITextField is as follows:
for(i=0; i<[fieldName count]; i++)
{
UITextField *name = [fieldName objectAtIndex:i];
frame = CGRectMake(fromLeft, fromTop, totalWidth, totalHeight);
name = [[[UITextField alloc] initWithFrame:frame] autorelease];
name.borderStyle = UITextBorderStyleRoundedRect;
name.returnKeyType = UIReturnKeyDone;
//name.placeholder = [fieldName objectAtIndex:i];
name.autocapitalizationType = UITextAutocapitalizationTypeWords;
name.adjustsFontSizeToFitWidth = TRUE;
name.keyboardType = UIKeyboardTypeDefault;
[name addTarget:self action:#selector(doneEditing:) forControlEvents:UIControlEventEditingDidEndOnExit];
[scroller addSubview:name];
fromTop = fromTop + 40;
}
Now I want to read values of each textbox in a button click (IBAction). Can anyone help me please?
You could use something like this to loop through all UITextFields that are subviews of self.view and add their text to a NSMutableArray:
for (UITextField *field in self.view.subviews) {
if ([field isKindOfClass:[UITextField class]]) {
if ([[field text] length] > 0) {
[someMutableArray addObject:field.text];
}
}
}
if your doneEditing: looks like this doneEditing:(id)sender then you can say:
UITextField *field = (UITextField *)sender;
NSString *myText = field.text;
EDIT:
To access a UITextField without setting as an instance variable you need to tag it when you create it:
[textField setTag:1];
then whenever you want to access it you can get it from its parent view by the tag:
UITextField *myTextField = [scroller viewWithTag:1];
NSString *myString = myTextField.text;
in your case, set the tag to i+1 for example to have all the textfield with unique tags.
implement the IBAction function like the following:
-(IBAction) doneEditing:(UITextField*)sender
{
NSString * val = sender.text;
}
try using the UITextFieldDelegate , i think its better for your case.
add each UITextField a Tag and by that you will recognise the UITextField.
NSString *value = sender.text;
If inside an IBAction, of course.
Which ignores that there is a set of text fields, and a single button action.
The simplest solution to the overall problem would be to store a set (or array) of text fields in an instance variable, and iterate over that set in the button action. But that is a rather coarse approach; it is probably better to use the text field delegate method and store text values directly in an array, using the button to trigger the save.
In addition, Apple HIG would tell you that you should update your data model as the text fields are edited, rather than use a "Save" button - which is poor UX design - unless, of course, the values of individual fields can interact.

How to Check the Value on "UITextField with tag" that which Textfield tag is pressed/Touch or Clicked?

I have The following code...
for (j=0; j<20; j++) {
if (j<20) {
txtField = [[UITextField alloc] initWithFrame:CGRectMake(110, txt_Pos_Y, 100, 15)];
txtField.borderStyle = UITextBorderStyleRoundedRect;
txtField.font = [UIFont systemFontOfSize:11];
txtField.tag = j;
txtField.placeholder = #"Enter Value";
txtField.autocorrectionType = UITextAutocorrectionTypeNo;
txtField.keyboardType = UIKeyboardTypeDefault;
txtField.returnKeyType = UIReturnKeyDone;
txtField.clearButtonMode = UITextFieldViewModeWhileEditing;
txtField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
txtField.delegate = self;
[scrollView addSubview:txtField];
[txtField release];
txt_Pos_Y = txt_Pos_Y + 20;
}
The code creates 20 textfields....All Textfields are editable when view will load.Now I want to give value.I want, on which textfield I click First, only that TextField will be editable and Rest will be NonEditable.
I gave the tag , txtField.tag = j;
now i am not able to figure out that which tag is pressed or clicked? And not able To make the TextField editable which i clicked First, and rest Non-Editable?
I tried this to check the condition in CalculateMethod() method that txtField.tag == 1 is clicked but this is not working.
-(void)CalculateMethod {
UITextField *txtFld = (UITextField*)[scrollView viewWithTag:1];
// I want if TextFeild "txtField.tag == 1" is clicked then Enter this condition
if(txtField.tag == 1){
double a;
a = Var_sqFt * Var_sqMtr;
txtFld.text = [[NSString alloc] initWithFormat:#"%.4f",a];
}
// I want if TextFeild "txtField.tag == 2" is clicked then Enter this condition
if(txtField.tag == 2){ // Here I want Only that
double a;
a = Var_sqFt * Var_sqMtr;
txtFld.text = [[NSString alloc] initWithFormat:#"%.4f",a];
}
}
So I have 2 questions
I want, on which textfield I click First, only that TextField will be editable and Rest will be NonEditable , how to do this?
Which TextField is clicked/Touch/Pressed , Like I tried in CalculateMethod() method?
To check which field started editing
You should look into the Delegate methods for your UITextFields. Simply set the delegate of all fields to self i.e. the controller creating the textFields. Then implement the UITextField delegate method
- (void)textFieldDidBeginEditing:(UITextField*)textField;
in the method check the tag of incoming parameter textField to perform your task.
To enable disable fields
Put all your fields in an NSMutableArray, iterate the array and only enable the field which matches the delegate parameter. Disable the rest.
[scrollView viewWithTag:1] will always give you the subview with tag 1 which is the same textView following your snippet. If you want to go through all the textViews you can do it with
for (UIView* aSubview in [self.scrollView subviews])
{
if ([aSubview isKindOfClass:[UITextView class]])
{
UITextView * typedTextViewSubview = aSubview;
switch (typedTextViewSubview.tag)
{
case 1 : {
double a;
a = Var_sqFt * Var_sqMtr;
typedTextViewSubview.text = [[NSString alloc] initWithFormat:#"%.4f",a];
}
.......
}
}
}
And you do not really need if (j<20) check as you already have given 20 as conditional upper limit of j iteration.

access string names using variables in FOR statement

is is possible to access objects using variables in a FOR statement?
Say i have declared:
UIImageView *UIImageView0;
UIImageView *UIImageView1;
UIImageView *UIImageView2;
and i have 3 objects in an array and i call a FOR statement if x in the array is equal to 2 i want it to add the value of x to the UIImageView name like UIImageView1 etc
I have tried:
for (int x=0; x<[theArray count]; x++) {
UIImageView[x].image = etc....
}
but it gives me a error on UIImageView[x]
subscript requires size of interface 'UIImageView'
any ideas? or is it even possible with a UIImageView?
Thanks
You don't have three elements in an array, though; you have three independent variables with similar names. If you created an actual array, containing the values of the three variables, then you could use the for loop -- and in fact, the syntax would be just as you've shown (using the actual name of the array variable, of course.)
You could say
UIImageView * views[3] = {UIImageView0, UIImageView1, UIImageView2};
and then use, for example, views[i].image in your loop.
In order to put your UIImageView into an array you need to create an instance NSMutableArray (for instance)
The above code does not show any array, instead you have three ivars
UIImageView *UIImageView0;
UIImageView *UIImageView1;
UIImageView *UIImageView2;
and to access those you would use the name, not an array.
If you however put them into an NSMutableArray you can access them using
NSMutableArray array = [[NSMutableArray alloc]
initWithObjects:UIImageView0, UIImageView1, UIImageView2, nil];
[array objectAtIndex:i ]; // where i is 0,1 or 2
...
[array release];
You can put your UIImageView to another array, and get the UIImageView from that array.
NSArray *imagesArray = #[imageView0, ...]
for(size_t i = 0; i<theArray.count; i++)
{
UIImageView *imageView = [imagesArray objectAtIndex:i];
}
Or you can use the "tag" property of UIView like:
UIImageView *image0 = ...;
image0.tag = 100; //or 0 or something else
[self.view addSubview:image0];
And then get the UIImageView by tag in your FOR statement:
for(size_t i = 0; i<theArray.count; i++)
{
UIImageView *imageView = [self.view viewWithTag:100+i];
}

Loop through labels iPhone SDK

Ok I have 8 labels and I want to loop through them but am having no luck.
This is what I have tried.
for (int i; i = 0; i < 10; i++)
{
double va = [varible1.text doubleValue] + i;
int j = 0 + I
label(j).text= [[NSString alloc]initWithFormat:#"%2.1f", va];
}
This errors out. My labels are named like this label0, label1, label2
Any help would be appreciated.
label(j) is NOT equivalent to label0, label1, etc.
You should create an NSArray of labels, then you can access them with [arrayOfLabels objectAtIndex:j]. If you're not sure what this means, please read the documentation about NSArray...
You should maybe add all your labels to a C array, probably in -viewDidLoad
UILabel* labels[] = { label0, label1, label2, ... };
(not entirely sure about the syntax)
and then access them like
labels[i].text = ...
By the way, I think you're leaking memory here:
labels[i].text = [[NSString alloc]initWithFormat:#"%2.1f", va];
initWithFormat: will return a string with a retain count of 1. labels[i].text will retain that value again. You should release the string after setting the label's text. I'd probably just autorelease it here:
labels[i].text = [[[NSString alloc]initWithFormat:#"%2.1f", va] autorelease];
or use stringWithFormat (which returns an autoreleased string):
labels[i].text = [NSString stringWithFormat:#"%2.1f", va];
for (UILabel *lbl in self.view.subviews)
{
[lbl setFont:[UIFont fontWithName:#"AppleGothic" size:22]];
}
it will change all the labels in your ViewController by just giving tags to labels.
If you cannot or do not want to put your labels in an array, you could iterate through the UIViews using the tag field as an index. You store the index numbers in them (either through IB or programatically) and then get each label using: (UIView *)viewWithTag:(NSInteger)tag.
See below (set theView to the view your labels reside in):
for (int i; i = 0; i < 10; i++)
{
double va = [varible1.text doubleValue] + i;
UILabel * label = [theView viewWithTag: i];
label.text= [[NSString alloc]initWithFormat:#"%2.1f", va];
}