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

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;
}
}

Related

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;
}

Crash due to removal of Elements like CCSprite from NSMutableArray

So, here's how it goes.
I am currently working on Cocos2d game, which consists of many Obstacles. One obstacle gets added on the screen at an interval of 10 seconds like this.
ObstacleSprite* newObstacle = [ObstacleSprite spriteWithFile:#"Obstacle.png" rect:CGRectMake(0, 0, 20, 20)];
newObstacle.position = ccp(mainPlayer1.position.x,10);
[self addChild:newObstacle];
[self.arrayForObstacles addObject:newObstacle];
Now, I insert these obstacles into the arrayForObstacles because I also want to keep checking whether the Obstacles and MainPlayer don't collide.
I check it with the help of this function.
- (void) checkCollisionWithObstacle
{
if(mainPlayer1.playerActive)
{
for(int i = 0; i < [self.arrayForObstacles count]; i++)
{
ObstacleSprite* newObstacle = [self.arrayForObstacles objectAtIndex:i];
if(newObstacle != nil)
{
if(CGRectIntersectsRect([mainPlayer1 boundingBox], [newObstacle boundingBox]))
{
mainPlayer1.livesLeft--;
}
}
}
}
}
THE ISSUE
Problem is when I get to certain score, one of the Obstacles gets deleted. Removal of Obstacles works as in First In-First Out (FIFO) mode. So, to delete obstacles, I write the following method :
- (void) keepUpdatingScore
{
//update new score
mainPlayer1.score+=10;
//remove obstacle when score increases by 5k
if(mainPlayer1.score > 5000 && mainPlayer1.score > 0)
{
mainPlayer1.playerActive = NO;
if([self.arrayForObstacles count] > 0)
{
CCLOG(#"count is %d",[self.arrayForObstacles count]);
ObstacleSprite* newObstacle = [self.arrayForObstacles objectAtIndex:0];
[self.arrayForObstacles removeObjectAtIndex:0];
[self removeChild:newObstacle cleanup:YES];
CCLOG(#"count is %d",[self.arrayForObstacles count]);
}
mainPlayer1.playerActive = YES;
}
else
{
}
It crashes when score crosses 5000 mark!
UPDATE
Crash happens when it again goes to the method checkCollisionWithObstacle.
This is the THREAD Look.
THis is the line Which crashes.
you seem to be using mainPlayer1.playerActive as a semaphore to block checking the checkCollisionWithObstacle loop from a delete in the keepUpdatingScore method (are they asynchronous ?). Assuming they are, the way you are blocking the loop access wont work if the code enters keepUpdatingScore AFTER the loop started in checkCollisionWithObstacle ... your mileage will vary.

Reduce number in text box by one for each button tap

I'm relatively new to Objective-C so this might be really simple to do: I have a text box in my application that displays an ammo count, so each time the user taps a fire button the number in the text box will go down by one (12 > 11 > 10, etc) to 0. I have tried using for and if statements, but they are not working (I may have used incorrect syntax). This is what I'm using right now, but obviously I need the
- (IBAction)fire {
[ammoField setText:#"11"];
}
- (IBAction)reload {
[ammoField setText: #"12"];
}
The simplest way would be to convert the text to a number, decrement that and the reset the text, i.e. replace the code in the fire method with:
NSInteger ammoCount = [ammoField.text integerValue];
ammoCount--;
ammoField.text = [NSString stringWithFormat:#"%d", ammoCount];
But don't do this, it will make baby Steve Jobs cry.
A better way would be to add a new variable to the class of type UIInteger that tracks the the number of bullets, i.e.:
// in interface
NSInteger _ammoCount;
...
// in implementation
- (IBAction)fire {
_ammoCount--;
if (_ammoCount <= 0) {
_ammoCount = 0;
fireButton.enabled = NO;
}
[ammoField setText: [NSString stringWithFormat:#"%d", _ammoCount]];
}
- (IBAction)reload {
_ammoCount = 12;
[ammoField setText: [NSString stringWithFormat:#"%d", _ammoCount]];
fireButton.enabled = YES;
}
Oh, and don't forget to call reload at some point early on to ensure _ammoCount and ammoField get initialised.
Set Instance Integer
int x;
set value of it
x = 12;
do change in method
- (IBAction)fire {
[ammoField setText:[NSString stringWithFormat:#"%i",x]];
x--;
}
set the value of count in viewdidload with an int variable
fire method decrease the count by 1
and reload method to return value to 12
log or use values accordingly
Try this:-
int i;
-(void)ViewDidLoad
{
i=12;
}
- (IBAction)fire
{
[ammoField setText:[NSString stringWithFormat:#"%d",i]];
i--;
}
- (IBAction)reload {
i = 12;
[ammoField setText: [NSString stringWithFormat:#"%d", i]];
}
Hope it will work for you. Thanks :)

i have a problem in UIImageView's animating

-(IBAction) change {
self.imageView.animationImages = myImages;
self.imageView.animationDuration = 2;
if(self.imageView.isAnimating == NO){
[self.imageView startAnimating];
NSLog(#"if bool = %d", self.imageView.isAnimating);
}
else {
self.imageView stopAnimating];
NSLog(#"else bool = %d", self.imageView.isAnimating);
}
}
hello, i'm studying iOS programming.
but i have a question.
i have a button and when i click the button, then this method will be called.
first i click the button, then this code will start the if statement. that's what i want.
i click the button again, i think that will execute the else statement.
but it always execute the if statement only.
why is that?
i really don't know why is that. please help me
I think setting the properties like animationImages or animationDuration will stop the animation, so that by clicking, you every time stop and then just after (re)start it in the if part. Try setting these two properties outside the action method you wrote, and just let the if/else sequence.
-(IBAction) change {
// set these two anywhere else
//self.imageView.animationImages = myImages;
//self.imageView.animationDuration = 2;
if(self.imageView.isAnimating == NO){
[self.imageView startAnimating];
NSLog(#"if bool = %d", self.imageView.isAnimating);
}
else {
self.imageView stopAnimating];
NSLog(#"else bool = %d", self.imageView.isAnimating);
}
}

Objective C - Help with UIButton showing variable Titles

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.