UIButton sender title problem - iphone

seems like a quite easy problem but I don't get it.
It have two UIButtons, one is titled 'next' the other is titled 'previous'. Both are linked to the same method. All I wanna do is change the variable 'helpStatus'depending on which button is pressed:
if([sender currentTitle] == #"next"){
helpStatus++;
}
if ([sender currentTitle] == #"previous"){
helpStatus--;
}
NSLog(#"%#", [sender currentTitle]);
the logged titels are 'next' and 'previous' just like it should be but it doesn't work and I don't know why.

You need to use isEqualToString otherwise you are just comparing if they are the same object, not if they are equal :)
if([[sender currentTitle] isEqualToString:#"next"]){
helpStatus++;
}
if ([[sender currentTitle] isEqualToString:#"previous"]){
helpStatus--;
}

I would not use the string. What happens if you decide to change the label? Consider using a tag instead.
e.g. b
button.tag = 100;
...
- (void)buttonPressed:(id)sender {
UIButton *button = (UIButton*)sender;
if(button.tag == 100) {
}
}
or in your case (I am kidding, sort of), even:
button1.tag = 1;
button2.tag = -1;
...
- (void)buttonPressed:(id)sender {
UIButton *button = (UIButton*)sender;
helpStatus+= button.tag;

Related

How to get instance variable name?

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

Why is NSLog causing EXC_BAD_ACCESS?

I have a tablecell with a button and I want to hook this in to a method call in my main class.
I have it working, but I need to identify the button pressed. SO I have done the following:
in cellForRowAtIndexPath I do the following:
cell.myBtn.tag = indexPath.row;
[cell.myBtn addTarget:self
action:#selector(viewClick:)
forControlEvents:UIControlEventTouchUpInside];
And I created the selector method like so:
- (void)viewClick:(id)sender
{
UIButton *pressedButton = (UIButton *)sender;
// EXC_BAD_ACCESS when running NSLog
NSLog(#"button row %#",pressedButton.tag);
if(pressedButton.tag == 1)
{
// NSString filename = #"VTS_02_1";
}
}
The problem is I get EXC_BAD_ACCESS when it hits this line: NSLog(#"button row %#",pressedButton.tag);
specify %i for int value
you have to use %# for only object, but int is not object,NSNumber is an object for that you can use %#.
NSLog(#"button row %i",pressedButton.tag);
try NSLog(#"button row %d", pressedButton.tag);
tag property is an int not an object.

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.

The same button should do multiple task

I want one of my button to act different on different taps. Because its the same button i am using every time a particular action happens.
Is there a way to do this?
Thanks,
Add an additional UIGestureRecognizer ;)
Single tap is the action what will be linked but you can add other kind of gestures like double tap, swipe, etc.
You can use the tag property of button; so inside your IBAction method.
-(void)buttonClicked:(id)sender{
UIButton *button = (UIButton *)sender;
if (button.tag == 1) {
// perform your required functionality
button.tag = 2;
}
else if (button.tag == 2) {
// perform your required functionality
button.tag = 3;
}
else if (button.tag == 3) {
// perform your required functionality
button.tag = 1;
}
}
And don't forget to set initial tag value to 1.
If you want your button to act different you would create different methods to do the different actions. Then whenever you want the buttons behaviour to change you should set the button to handle the desired action.
So for the first action:
[button addTarget:self action:#selector(method1:) forControlEvents:UIControlEventTouchUpInside];
- (void) method1
{
//set button to handle method 2
[button addTarget:self action:#selector(method2:) forControlEvents:UIControlEventTouchUpInside];
}
- (void) method 2
{
}
The button just calls a method in your view controller when tapped. From there you do something like this:
if (internalState == FOO) {
[self doA];
} else {
[self doB];
}

How to assign a value or title to a UIbutton instance so I can access it when I press the button?

I want to create a basic app where you have 8 numbered buttons, with a randomly generated number on each. You are given a total value, and have to click on buttons whose numbers add up to that value.
I need to show which buttons have been 'used' already (I hope to use the selected state for that, as I am using a custom button).
When you press a button, it needs to add the correct value to the 'totalSoFar and change the button to it's selected state.
The plan is that I currently have 8 UIButtons (b1, b2 etc). I have generated a random array of numbers, that I want to assign as the title of the button.
I have tried about a million variations on the theme of [b1 setTitle etc] but can't get it to work.
I have added a textview on top of the button (n1, n2...) that now displays my random numbers instead.
I have got it so that when you press a button, it gets the tag of that button, and then finds the matching position in the array, so I can use that value in the 'what's the total of all the buttons I have pressed' calculation. I cannot however figure out how to access the sender button in order to tell it to change to selected.
I'd much rather do this by just changing the title of the button, rather than having to have an extra textfield.
I am still quite new to Objective C, having previously only coded in actionscript for Flash, and I'm only asking after spending about 4 hours trying to search for a solution online (and swearing at my computer a lot...)
Here's what I have so far... I have tagged each button, so that b1 has a tag of 0, b2 has a tag of 1 etc...
-(IBAction) pressed:(id)sender {
int i;
UIButton *button = (UIButton *)sender;
for (i=0; i<8; i++) {
if ([button tag] == i)
{
//returns value in array as a string
NSString *temp2 = [pnumbers objectAtIndex:i];
//checks string value to see what total to add
if ([temp2 isEqualToString:#"1"]) {
total +=1;
}
if ([temp2 isEqualToString:#"2"]) {
total +=2;
}
if ([temp2 isEqualToString:#"3"]) {
total +=3;
}
if ([temp2 isEqualToString:#"4"]) {
total +=4;
}
if ([temp2 isEqualToString:#"5"]) {
total +=5;
}
if ([temp2 isEqualToString:#"6"]) {
total +=6;
}
if ([temp2 isEqualToString:#"7"]) {
total +=7;
}
if ([temp2 isEqualToString:#"8"]) {
total +=8;
}
if ([temp2 isEqualToString:#"9"]) {
total +=9;
}
}
}
}
I don't want to just make a new function for each separate button (as I plan to have 64 buttons in the end) in order to be able to access which button it was without lots of if and for statements. If nothing else, that seems like bad coding to me!
Hope this all makes sense...
I mostly just want to make the damn thing show the selectedState for the correct button once I've clicked on it. I can live with the textfields!
EDIT - for the record, I've now managed to get it to the selected state, by using
[b1 setSelected:FALSE];
at the start, and then adding
UIButton *button = (UIButton *)sender;
[sender setSelected:TRUE];
before the for loop. Still not sure how to get it to deselect the next time it is clicked though.
It seems like your code could be simplified:
- (IBAction) pressed:(UIButton *)sender {
int buttonIndex = [button tag];
total += [[pnumbers objectAtIndex:buttonIndex] intValue];
}
Many thanks to all who helped!
I finally managed to achieve what I wanted using this beautifully simple bit of code:
-(IBAction) pressed:(id)sender {
UIButton *button = (UIButton *)sender;
if ([sender isSelected] ==FALSE) {
[sender setSelected:TRUE];
int buttonIndex = [button tag];
total += [[pnumbers objectAtIndex:buttonIndex] intValue];
NSLog(#"%i", total);
}
else {
[sender setSelected:FALSE];
int buttonIndex = [button tag];
total -= [[pnumbers objectAtIndex:buttonIndex] intValue];
NSLog(#"%i", total);
}
}
Firstly, you're probably looking for -[UIButton setTitle:forState:], where state is probably going to be UIControlStateNormal. The other thing you might want to use is -[NSString intValue].
This would let you do
total += [temp2 intValue];
rather than your case statement.
First, you should be able to simplify your current code a bit:
- (void)pressed:(id)sender
{
UIButton *button = (UIButton *)sender;
total += [sender tag];
}
Then you can call the button's -setSelected: method to change its state:
- (void)pressed:(id)sender
{
UIButton *button = (UIButton *)sender;
total += [sender tag];
[button setSelected:YES];
}
When you create the buttons, use the following method to set its title:
- (void)setTitle:(NSString *)title forState:(UIControlState)state
If you use UIControlStateNormal as the argument, it will use the title for all three of the button's possible states.