How to get instance variable name? - iphone

I created a simple iPhone screen with two UIButtons programmatically like below.
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *buttonOne = [UIButton buttonWithType:UIButtonTypeRoundedRect];
buttonOne.frame = CGRectMake(60, 70, 200, 40);
[buttonOne setTitle:#"One" forState:UIControlStateNormal];
[self.view addSubview:buttonOne];
UIButton *buttonTwo = [UIButton buttonWithType:UIButtonTypeRoundedRect];
buttonTwo.frame = CGRectMake(60, 250, 200, 40);
[buttonTwo setTitle:#"Two" forState:UIControlStateNormal];
[self.view addSubview:buttonTwo];
}
Now on press of button with title as "One", I want to get the variable name as "buttonOne", similarly on press of button with title as "Two" I want to get the variable name as "buttonTwo".
I am not finding a way to get the variable name. Any help? Thanks in advance

First off I'd like to disclaim that this is not good coding style. I assume you're doing this because of some special/unique case, or as a proof of concept. In a production app, this is NOT the way to go. You should set your buttons as properties/ivars and you can compare them when they're pressed, or you can assign tags, or separate targets/selectors for each button. Anything you can do to avoid this approach is good because to be honest this approach is kind of terrible (see note at the end of next paragraph about nil/0 values).
You can check out this code below from a previous SO answer - it will return the name of the ivar given the pointer. However, you have to declare your buttons as ivars and not local variables. Also, if two ivars are nil, it will report the same. So this will only work if all your object ivars are not nil, and your primitive type ivars are not 0.
#import <objc/objc.h>
- (NSString *)nameOfIvar:(id)ivarPtr
{
NSString *name = nil;
uint32_t ivarCount;
Ivar *ivars = class_copyIvarList([self class], &ivarCount);
if(ivars)
{
for(uint32_t i=0; i<ivarCount; i++)
{
Ivar ivar = ivars[i];
id pointer = object_getIvar(self, ivar);
if(pointer == ivarPtr)
{
name = [NSString stringWithUTF8String:ivar_getName(ivar)];
break;
}
}
free(ivars);
}
return name;
}
So add a method buttonPressed: as follows:
- (void)buttonPressed:(id)sender {
if ([sender isKindOfClass:[UIButton class]]) {
NSString *buttonName = [self nameOfIvar:sender];
//Now you can do something with your button name
}
}
Source of first block of code: Get property name as a string

we can get only button title name by this way buttonOne.titleLabel.text.
we can't get variable name

Related

How to create Multiple buttons programmatically, get button name whenever press on particular button?

I want to create multiple buttons using MutableArray count. After creating the button, whenever pressing on particular button, I want to display that button name in a label. But Once press on button, it is always showing the MutableArray last index value name. Please help in this problem. I am fresher ti iOS. It's my code.
-(void)ViewDidLoad {
NSMutableArray *Mute_array=[[NSMutableArray alloc]initWithObjects:#"One", #"Two", #"Three", #"Four", #"Five", nil];
for (int k=0; k<[Mute_array count]; k++){
UIButton *btn_sub_category = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn_sub_category addTarget:self action:#selector(clicks:) forControlEvents:UIControlEventTouchDown];
[btn_sub_category setTitle:[Mute_Sub_Category objectAtIndex:k] forState:UIControlStateNormal];
btn_sub_category.frame = CGRectMake(278, k*130, 483, 44);
[self.view addSubview:btn_sub_category];
}
}
-(void)clicks:(id)sender{
label.text=[btn_sub_category currentTitle];
//Here a want to send the name of that clicked button current title
}
But, here button current title is always showing MutableArray last object "Five" only. I want pressed button current title.
-(void)clicks:(id)sender{
UIButton *theButton = (UIButton*)sender;
NSString *theButtonTitle = [theButton titleForState:UIControlStateNormal]
NSLog(#"theButtonTitle :- %#", theButtonTitle);
label.text=theButtonTitle;
//Here a want to send the name of that clicked button current title
}
Try this code.
I using following method to get title of button
titleForState:
Returns the title associated with the specified state.
- (NSString *)titleForState:(UIControlState)state Parameters
state
The state that uses the title. The possible values are described in UIControlState.
Return Value
The title for the specified state. If no title has been set for the
specific state, this method returns the title associated with the
UIControlStateNormal state.
Read Documentation https://developer.apple.com/library/ios/documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html#//apple_ref/occ/instm/UIButton/titleForState:
Try like this:
-(void) clicks:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
UIButton *button = (UIButton*)sender;
NSString *title = button.currentTitle;
// do whatever you want with title
}
}
Try Like,
-(void)clicks:(id)sender{
UIButton *resultebutton= (UIButton*)sender;
label.text=resultebutton.titleLabel.text;
}

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.

iPhone - call UISwitch that is generated in a UIView when a button is pressed

To clarify my question, my program has three lightbulb on the screen (Customized UIButton)
when any lightbulb is pressed, I programatically generate a UIView with a switch on it
when I turn on the switch, corresponding lightbulb will light up (change its background image)
However, I have trouble accessing this UISwitch since I can't declare it publicly
My code goes something like this:
#property buttonA;
#synthesize buttonA;//all three buttons have their background image set to 'off.png'
- (IBAction)lightBulbPressed:(UIButton *)sender
{
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(1,1, 64, 64)];
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0,0,64,64)];
[mySwitch addTarget:self action:#selector(onOrOff) forControlEvents:UIControlEventValueChanged];
[myView addSubview:mySwitch]
[self.view addSubview:myView];
}
So what troubles me is how to program the selector onOrOff, so that it knows which switch is being touched and change the background image of corresponding button accordingly.
Think about your method:
- (IBAction)lightBulbPressed:(UIButton *)sender {
// your method
}
You already know who called it. This piece of information is stored in sender.
So you can save it and use later in onOrOff
By the way, if you are using UISwitch you have to check
UIControlEventValueChanged
and not UIControlEventTouchUpInside.
EDIT: To pass your sender you can store its value to a NSString *buttonTapped declared in your .h file
- (IBAction)lightBulbPressed:(UIButton *)sender {
if (sender == bttOne) {
buttonTapped = #"ButtonOneTapped";
} else if (sender == bttTwo) {
buttonTapped = #"ButtonTwoTapped";
} else if (sender == bttThree) {
buttonTapped = #"ButtonThreeTapped";
}
// your method
}
- (void)onOrOff {
if ([buttonTapped isEqualToString:#"ButtonOneTapped"]) {
// Button One
} else if ([buttonTapped isEqualToString:#"ButtonTwoTapped"]) {
// Button Two
} else if ([buttonTapped isEqualToString:#"ButtonThreeTapped"]) {
// Button Three
}
}
One way to do so, is taht you give them distinct tag numbers in IB, and in - (IBAction)lightBulbPressed:(UIButton *)sender method, get their tag. e.g. NSInteger pressedButtonTag = [sender tag];, and go from there.
Also, instead of alloc/init myView every time user presses a button, you can add that view in IB, add the switch to it, put in the hierarchy of the owner but not the view, and set an outlet to it in .h. Call it whenever you need it, and again, access the switch by tag e.g. ( UISwitch *mySwitch = (UISwitch *)[myView viewWithTag:kSwitchTag]; ) and do whatever you want to do (on or off), add it to the subview and remove it later. This is more efficient.

changing a button's text from another method when the buttons are in a subclass?

How do you access a button that's in a subview of a view?
I have a viewController 'GamePlay', which has a scrollview in it called 'gameScroll'. Within this scrollview I have about 100 buttons, each with a tag, and I want to be able to change the text of the button from another method.
- (void) viewDidLoad {
//Created buttons in a for-loop, assigning each a tag
//numOfButtons is total number of buttons created
}
I imagine it would be something like this? but I cant seem to find an answer on exactly how i do it when the button is in a subview
- (void) otherMethod {
for (int i=0; i<numOfButtons; i++) {
// tagsForAction = get list of buttons that need to be changed from another array
for (j=0; j<tagsForAction.length; j++) {
intTagForAction = [tagsForAction objectAtIndex:j];
if (i = tagForAction) {
UIButton* button = [Gameplay.gameScroll.view viewWithTag:tagForAction];
button.title = #"A";
}
}
}
}
I know this code isnt totally right. Im just giving you an idea of the process. I can do everything except this part in the if statement:
UIButton* button = [Gameplay.gameScroll.view viewWithTag:tagForAction];
button.title = #"A";
so how do I change the text of these buttons?
NSArray *subViewList = [gameScroll subviews];
for (id button in subViewList)
{
if ([button isKindOfClass:[UIButton class]])
{
[button setTitle:#"OK" forState:UIControlStateNormal];
}
}
Try this code
You don't have to use the for loop like that, you can get an array of subviews from any view by doing something like [someView subviews]. So, inside of your otherMethod function you can do something like:
for (UIView *v in [gameScroll subviews]) {
if (v.tag == <some_int_here>) {
[v setTitle:#"Some other title" forState:UIControlStateNormal];
}
}
I'm not exactly sure what your criteria is for determining which buttons inside the gameScroll view have to get updated, but you can work from here.

IBAction used with Dynamically added UIbuttons

Good Evening all!
I have some UIButtons added dynamically into my view and of course I have an IBAction which handles button events.
The problem is: How can I detect which button is pressed if the only thing I know is the (id)sender and the array of buttons?
Buttons are never the same, every button has a different behavior. When I want to use static buttons and connect them through the IB I use something like this :
-(IBAction)doSomething:(id)sender
{
if(sender == button1)
dosomething;
if(sender == button2)
dosomething else;
if(sender == button3)
dosomething3;
}
In my case this does not work because there is no button1, button2, button3 but a MutableArray of buttons which have the same name as they were allocated with it. Button!
I tried using the way above but with no success and i tried also getting the tag of a button but I have nothing to compare it to!
I would really appreciate your help.
sincerely
L_Sonic
PS Dynamicaly means that i am creating the buttons in random time during run time like this
-(void)configActionSheetView
{
buttonView = [[UIView alloc]initWithFrame:CGRectMake(0.0,460, 60, 480)];
[buttonView setBackgroundColor:[UIColor blackColor]];
[buttonView setAlpha:0.6];
for (int i = 0 ;i<[buffButtons count];i++)
{
UIButton *customButton = [buffButtons objectAtIndex:i];
customButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//UILabel *customLabel = [[UILabel alloc]init];
//[customButton setTag:(i)+11];
[customButton addTarget:self action:#selector(activateBuffEffect:) forControlEvents:UIControlEventTouchUpInside];
[customButton setAlpha:1.0];
customButton.frame = CGRectMake(8.0, 5+(50*i), 44.0, 44.0);
[customButton setTitle:nil forState:UIControlStateNormal];
buttonView.frame = CGRectMake(0, 460, 60, 50+(44*(i+1)));
[buttonView addSubview:customButton];
}
}
this is inside a functions and gets called during run time. the buffButtons is a mutableArray with buttons that gets populated during runtime.
i need a solution like this i cannot get a different eventhandling method for everybutton.
When you was "added dynamically" I assume you mean that they are created from some piece of code. Since all buttons to different things and you know what a certain button should do, why don't you add different actions to different buttons?
UIButton *myCreatedButton = [[UIButton alloc] init];
[myCreatedButton addTarget:self
action:#selector(doSomething:)
forControlEvents:UIControlEventTouchUpInside];
UIButton *myOtherCreatedButton = [[UIButton alloc] init];
[myOtherCreatedButton addTarget:self
action:#selector(doSomethingElse:)
forControlEvents:UIControlEventTouchUpInside];
In the above code the target (set to self) is the class where the method you want to run is found, the action is the method that you want to run and the controlEvent is what should cause the method to run.
If you did it like this you would split the code in different methods like these (you do not need to specify them in the header):
-(void)doSomething:(id)sender {
// do somthing here ...
}
-(void)doSomethingElse:(id)sender {
// do somthing else here ...
}
This way you don't need to know what button was pressed since the correct code would get called anyway. Besides it makes it cleaner if you need to change the code for some of the buttons.
Found it!
-(IBAction)buttonTapped:(id)sender {
UIButton *btn = (UIButton *)sender;
NSLog(#"tapped: %#", btn.titleLabel.text);
[self anotherIBAction:sender];
}
now i can get the tag from the btn :D
thnk you!
Why not add a tag the button and then get the tag number from (id)sender in the selector function?