Objective C - Help with UIButton showing variable Titles - iphone

First off I am a rookie so any help is appreciated. I have written the following code to change the title of the button every time it is initiated. When I test the code, I can see the new button label for a fraction of a second and then the button is blank again (as it had started off). I only see the first three touches, so I am thinking that there is also something wrong with my counting method. The code is as follows:
-(IBAction)pressButton:(id)sender {
static int counter = 0;
if (counter == 0) {
[[sender titleLabel] setText:#"not answered"];
}else if (counter == 1) {
[[sender titleLabel] setText:#"Pressed Once"];
}else if (counter == 2) {
[[sender titleLabel] setText:#"Pressed Twice"];
}
counter += 1;
if (counter >2) {
counter = 0;
}
}
Thank you in advance for your help!

You want to use:
[(UIButton *)sender setTitle:#"XXX" forState:UIControlStateNormal];
Setting the label directly isn't going to work because it's manipulated internally by the button logic.

Related

Changing button label not working properly with if-else method

it is probably a very simple problem but I spent already a lot of time on it and just have given up...
I have a button and a textfield for speed calculations. I want the button label change once the button is pressed (km/h >> mph >> m/s >> km/h and so on) and speed recalculated. It sometimes works fine but very often it jumps to "else" statement even if the CurrentSpeedValue is #"km/h". Could anyone help? Maybe it would be better to use switch-case method but how should it be stated?
- (IBAction)speedChange:(id)sender {
//CurrentSpeedUnit is saved to NSUserDefault in another action
if (CurrentSpeedUnit == #"km/h") {
[sender setTitle:#"mph" forState:UIControlStateNormal];
CurrentSpeedUnit = #"mph";
float speedToPrint = ([textSpeed.text floatValue]) / 1.609344;
textSpeed.text = [[NSString alloc] initWithFormat:#"%.3f", speedToPrint];
} else if (CurrentSpeedUnit == #"mph") {
[sender setTitle:#"m/s" forState:UIControlStateNormal];
CurrentSpeedUnit = #"m/s";
float speedToPrint = ([textSpeed.text floatValue]) * 1.609344 / 3.6;
textSpeed.text = [[NSString alloc] initWithFormat:#"%.3f", speedToPrint];
} else {
[sender setTitle:#"km/h" forState:UIControlStateNormal];
CurrentSpeedUnit = #"km/h";
float speedToPrint = ([textSpeed.text floatValue]) * 3.6;
textSpeed.text = [[NSString alloc] initWithFormat:#"%.3f", speedToPrint];
}
}
For string comparison you need to use
isEqualToString
For Example:
if ([CurrentSpeedUnit isEqualToString:#"km/h"])
{
// Perfrom Action
}...
You should not compare strings like that (you compare pointers but not the contents). Use isEqualToString.
i.e.
if ([CurrentSpeedUnit isEqualToString:#"km/h"]) {
...
but not your
if (CurrentSpeedUnit == #"km/h") {
It may work sometimes, but just remember to avoid comparing strings with ==

I need a way to detect last Five clicks time on my UIButton

I have an UIButton that the user must click on it 5 times in three seconds, im trying to implement a method for that, but im getting the correct result if the user clicked on the button 5 times in 3 seconds in a row, if the user clicked once and stopped for 2 seconds for example, the counter take the first click in the calculation.
in a short words, i need a method that detect the last five clicks and know if the clicks were in three second or not...
Here is my old code:
-(void)btnClicked{
counter++;
if (totalTime <=3 && counter==5) {
NSLog(#"My action");
// My action
}}
I know that my code is too simple, so that why i asked you pro's
Try altering this example appropriately:
// somewhere in the initialization - counter is an int, timedOut is a BOOL
counter = 0;
timedOut = NO;
- (void)buttonClicked:(UIButton *)btn
{
if ((++counter >= 5) && !timedOut) {
NSLog(#"User clicked button 5 times within 3 secs");
// for nitpickers
timedOut = NO;
counter = 0;
}
}
// ...
[NSTimer scheduledTimerWithTimeInterval:3.0
target:self
selector:#selector(timedOut)
userInfo:nil
repeats:NO
];
- (void)timedOut
{
timedOut = YES;
}
Simply have an array with the timestamp of the last four clicks, and every time there is a click, check if the previous four are within 3 seconds from the current time. If it is not the case, discard the oldest timestamp and replace with current time, but if it is the case, you got your event and you can clear the array so that they are not used in the next 5-clicks-in-3-seconds event.
Here is 'my version' of H2CO3's code. This should suit your requirement better.
int counter = 0;
BOOL didTimeOut = NO;
- (void)buttonClicked:(UIButton *)button {
counter ++;
if (counter == 1) {
didTimeOut = NO;
[NSTimer scheduledTimerWithTimeInterval:3.0f
target:self
selector:#selector(timedOut)
userInfo:nil
repeats:NO
];
} else {
if ((counter >= 5) && !didTimeOut) {
//Do your action as user clicked 5 times in 3 seconds
counter = 0;
didTimeOut = NO;
}
}
}
- (void)timedOut {
didTimeOut = YES;
}

compare between two tagged objects?

I have 2 buttons, each one with tag. how can I compare between them, each with his own tag and image. for example:
// sender is (UIButton *)sender.
if ((sender.tag == 1)theImageOnTheButton == (sender.tag == 2)theImageOnTheButton
{
// egual
}
else
// not egual
so, if the sender than tagged as 1, his image is equal to the sender with tag 2, his image are equal, say equal, else, say that they are not egual. how can I do that?
the original code is:
-(void)flipView:(UIButton*)sender
{
x = x + 1;
if (x == 1)
{
// When flipping the first card
NSLog(#"X == 1");
[sender setTag:1];
}
else if (x == 2)
{
// When flipping the second card
NSLog(#"X == 2");
x = 0;
[sender setTag:2];
if ((sender.tag == 2) == (sender.tag == 1))
{
NSLog(#"IGUAL");
}
else
{
NSLog(#"NOT EGUAL");
}
}
}
Thanks allot.
[sender setTag:2];
and then -
if ((sender.tag == 2) == (sender.tag == 1))
when already tag is set to 2, then how can it be equal to 1? Wrong logic.
If I have more than two buttons then how can i compare the images?
suppose you have two buttons with tags
IBOutlet UIButton *btn1, *btn2;
btn1.tag = 1;
btn2.tag = 2;
connect these two IBOutlet buttons to your buttons in your xid file and for both add a common IBAction.
-(IBAction)checkingBtns:(id)sender
{
if([sender tag] == 1){
//Do what ever with your btn1 change color, change text, change image
}
if([sender tag] == 2){
//Do what ever with your btn2 change color, change text, change image
}
}
hope this will help you !! properly connect the oulets and actions for proper function

iPhone: Button Level

i'm new to iPhone.Is there any way to set 3 images to button, and when I will click the button it will change button image in a circle ? Thanks...
In your IBAction method for the button click, you can keep a count of which image you are on, and also have all 3 UIImages ready to go (so there isn't the load everytime..unless the images are large (which they shouldn't be for a button) and check it and rotate it basically with something simple like (assumes you have 3 instance variables of UIImages ready that are already initialized with the images.:
-(IBAction) myButtonPress:(id)sender {
int imageCounter = 0;
if(imageCounter == 0) {
[myButtonImage setBackgroundImage:image1 forState:UIControlStateNormal];
imageCounter++;
}
else if(imageCounter == 1) {
[myButtonImage setBackgroundImage:image2 forState:UIControlStateNormal];
imageCounter++;
}
else if(imageCounter == 2) {
[myButtonImage setBackgroundImage:image3 forState:UIControlStateNormal];
imageCounter = 0;
}
//Do other button press stuff
}

How to get UIButtons title in an array to be shown each one by one in a timed sequence

In my program, I have a series of UIButtons in an array that I would like its title to be shown each one at a time one by one in a timed sequence after executing a function that has a while loop.
I have an IBAction attached to the buttons and when touched will call another function that will do some operation and in the end, will change the UIButtons title in that array.
The problem is that it changed the whole buttons title simultaneously after executing that method but I want the title to be shown one by one in a timed sequence.
To illustrate clearly, here are my codes:
-(IBAction)touchedButton1:(id)sender
{
[self calculateSteps:0];
}
-(void)calculateSteps:(NSUInteger)hole_index2
{
index = hole_index2;
NSNumber *tempNumber = [marblesArray objectAtIndex:index];
stones = [tempNumber intValue];
[marblesArray replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:0]];
[[buttonsArray objectAtIndex:index] setTitle:[NSString stringWithFormat:#"%d", [NSNumber numberWithInt:0].intValue] forState:UIControlStateNormal];
while(stones > 0) {
if (player == PLAYER_A && stones >= 1 && index == 6) {
NSNumber *tempNumber3 = [storeArray objectAtIndex:0];
NSUInteger tempInt3 = [tempNumber3 intValue];
tempInt3++;
[storeArray replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:tempInt3]];
[buttonPlayerA setTitle:[NSString stringWithFormat:#"%d", [NSNumber numberWithInt:tempInt3].intValue] forState:UIControlStateNormal];
stones--;
if (stones == 0) { // end in PLAYER A's store
NSLog(#"end in big hole player A");
return;
}
}
if (player == PLAYER_B && stones >= 1 && index == 12) {
NSNumber *tempNumber4 = [storeArray objectAtIndex:1];
NSUInteger tempInt4 = [tempNumber4 intValue];
tempInt4++;
[storeArray replaceObjectAtIndex:1 withObject:[NSNumber numberWithInt:tempInt4]];
[buttonPlayerB setTitle:[NSString stringWithFormat:#"%d", [NSNumber numberWithInt:tempInt4].intValue] forState:UIControlStateNormal];
stones--;
if (stones == 0) { // end in PLAYER B's store
NSLog(#"end in big hole player B");
return;
}
}
index++;
if (index >= NUM_HOLES) index = 0;
NSNumber *tempNumber2 = [marblesArray objectAtIndex:index];
tempInt2 = [tempNumber2 intValue];
tempInt2++;
[marblesArray replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:tempInt2]];
NSLog(#"Number in marblesArray index: %d", [NSNumber numberWithInt:tempInt2].intValue);
[[buttonsArray objectAtIndex:index] setTitle:[NSString stringWithFormat:#"%d", [NSNumber numberWithInt:tempInt2].intValue] forState:UIControlStateNormal];
stones--;
}
}
So, I have tried to put NSTimer in the calculateSteps method and also in that while loop but couldn't get to work. I guess maybe the while loop function fast enough that it didn't get the chance to get NSTimer to work in time.
I know it could work if I use if timer == 1, or else if timer == 2, etc as the timer increase, each button associated with it will change after that interval. However, when I tried to use for (timer == 1; timer < stones; timer++) , it doesn't show the buttons title each one by one but simultaneously after it is done with the loop. Am I wrong with my logic?
Also, I've tried to put sleep(2) in the while loop also, it works for the NSLog(#"Number in marblesArray index:...") appearing each 2 seconds but still the buttons array title still shown simultaneously after while loop completed.
I'm not sure how can I get the buttons title in that array to be shown each one by one in a timed sequence. Have been trying for 2 days but couldn't get it to work.
Appreciate if anyone out there who can help me. I don't know if it's my logic or if there's other function that can be used to solve this issue.
Thank you very much in advance.
Yes, you could used :
NSTimer
or just performSelector:withObject:afterDelay: of any NSObject subclass.
You can not use sleep or loop in main thread. It will block the HMI.
But I don't really understand your code and your explanation...
In the target selector of the timer, you could have a static int to count the number of ticks
example (very simple):
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(onTimer) userInfo:nil repeats:NO];
-(void)onTimer{
static int ticks = 0;
ticks++;
if (ticks==1) {
//TODO
} else if (ticks==2) {
//TODO
} else if (ticks==3) {
//TODO
} else {
//TODO
ticks=0;
}
}