I have this NSMutable array. Reading it one by one after every two seconds and updating textview. But now i want is to read from NSMutable array one by one at different timeintervals than every two seconds. How i can do that.
- (void)viewDidLoad{
myArray = [[NSMutableArray alloc]initWithObjects:#"String1",#"String2",#"String3",#"String4", #"String5",..... nil];
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(updateText:)
userInfo:nil
repeats:YES];
- (void)updateText:(NSTimer *)theTimer
{
if (index < [myArray count])
{
myTextView.text = [myArray objectAtIndex:index];
index++;
}
else
index = 0;
}
}
Thanks for help.
If all you need is to change the interval value every time the view loads you can try with a random number, in the next example it'll return a random number between 2 and 10:
[NSTimer scheduledTimerWithTimeInterval:arc4random() % 10 + 2
target:self
selector:#selector(updateText:)
userInfo:nil
repeats:YES];
Simple: cancel the timer each time and recreate it with the desired interval (hang onto a reference to the timer of course).
in your updateText selector just create a new NSTimer with different intervals until there are no more objects in the array.
Use performSelector:withObject:afterDelay, but using a random delay!
[self performSelector:#selector(updateText:) withObject:nil afterDelay:arc4random()%10+2];
Related
So currently I have a UISlider in a UIViewcontroller that is meant to start animations within subviews when the user slides.. Basically when the user slides I have this battery with a filling in it that fills the empty battery image with a bar to indicate power within a cell, and the user can slide to see the energy the battery has at certain times of the day.
At the moment, when the View loads I would like the UISlider to AUTOMATICALLY start sliding from the beginning of the slider and scroll to the end within, lets say 5 seconds.
I implemented a loop that cycles through all the values of the uislider using this loop
for (int i = 0; i < [anObject count] - 2; i++)
{
sleep(.25);
NSUInteger index = (NSUInteger)(slider.value + 0.5); // Round the number.
[slider setValue:index animated:YES];
}
[anObject count] - 2 is equal to 62 at this time of day but will change and increment every 15 seconds because I'm fetching data from a server.
But that aside, why doesn't this work? The loop?
EDIT:
So heres what I did with NSTIMER
[NSTimer timerWithTimeInterval:0.25 target:self selector:#selector(animateSlider) userInfo:nil repeats:NO];
and animateSlider looks like this:
- (void)animateSlider:(NSTimer *)timer
{
NSLog(#"Animating");
NSUInteger index = (NSUInteger)(slider.value + 0.5); // Round the number.
[slider setValue:index animated:YES];
}
But no luck... Why isn't NSTimer "firing"..... I remmeber vaguely there was a method that FIRES an nstimer method but not sure if that's needed...
EDIT:
Ahh it does need "Fire"....
NSTimer *timer = [NSTimer timerWithTimeInterval:0.25 target:self selector:#selector(animateSlider) userInfo:nil repeats:NO];
[timer fire];
But for some reason it only fires once.... Any ideas ?
"for some reason it only fires once..."
If you changed the NSTimer set up to this:
NSTimer *timer =
[NSTimer scheduledTimerWithTimeInterval:0.25
target:self
selector:#selector(animateSlider:)
userInfo:nil
repeats:YES];
This would schedule the timer on the current run loop immediately.
And since the "repeats" parameter is "YES", you'd then repeat the timer every quarter second, until you invalidate the timer (which you should do when the ending condition is reached, like when the slider reaches its destination).
P.S. You'd need to change the selector method declaration of your timer's target slightly. According to Apple's documentation, "The selector must correspond to a method that returns void and takes a single argument. The timer passes itself as the argument to this method."
So declare "animateSlider" like this instead:
- (void)animateSlider: (NSTimer *) theTimer;
I have an application in which I want that when I run my application initially it should show a screen for 2 seconds that displays warning about the app and just after 2 seconds a countdown should start from 5 seconds that should decrement from 5 second to 1 second.
There are two ways:
[NSTimer timerWithTimeInterval: .....]
[self performSelector: withObject: afterDelay:]
so if i got your point you want to display a warning screen and after 2 seconds you want to show the user count down start from 5 and end at 1 .. well this can done easy by using a timer and counter as following :
define a NSTimer and start it once the warning view is shown .. your definition will be like this:
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerFires) userInfo:nil repeats:YES];
[timer fire];
define a global integer and set its initial Value to 7 (lets suppose you name it counter).
-in timerFires selector you decreament counter by 1 and check its value when its equal to 5 start to show its vlaue on UILabel for example and when its 1 invalidate the timer and do you what you want at this point .. the timerFires will be like this:
- (void)timerFires
{
counter --;
if(counter ==5)
{
//show its Value
}
if(counter ==1)
{
[timer invalidate];
timer = nil;
//Do other stuff
}
}
[NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(updateFunction) userInfo:NULL repeats:YES];
In updateFunction you can write your code for count down.
You can also set "repeats:NO" and to call the updateFunction at the end of itself if it is necessary
I'm struggling with this. I saw some code where you can do this :
- (void)startTimer {
pauseTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(doActions) userInfo:nil repeats:YES];
}
Then call it in doActions.
Problem is i want to call it while a button is being pressed, and do actions is an IBaction. I keep getting a sigAbrt.
Can someone give me some sample code where you cay change a label from 'on' to 'off' every 1 second while a button is being pressed?
EDIT
i mean if doActions looks like this
- (IBAction) doActions {
for(int j; j<100; j++){
theLabel.hidden != theLabel.hidden;
//Does invalidate timer go here?
}
}
It still isn't clear to me, what you're trying to accomplish: I would have found it much easier, if you simply had it written down in plain english, after all.
That said, here's what I think will get you where you want to go:
// Assuming ivars:
// NSTimer* toggleTimer
// NSUInteger toggleCount
- (void)toggleTimerFired:(NSTimer*)timer
{
if ( toggleCount++ >= 100 ) {
[self stopToggling:self];
return;
}
// do whatever you need to do a hundred times here
}
- (IBAction)stopToggling:(id)sender
{
[toggleTimer invalidate], toggleTimer = nil; // you don't want dangling pointers...
// perform any other needed house-keeping here
}
- (IBAction)startToggling:(id)sender
{
[self stopToggling:self]; // if `startToggling:` will NEVER be called when a timer exists, this line CAN be omitted.
toggleCount = 0;
toggleTimer = [NSTimer scheduledTimerWithTimeInterval:1. target:self selector:#selector(toggleTimerFired:) userInfo:nil repeats:YES];
}
Depending on what exactly you want to do, startToggling: needs to be sent on either touchUpInside or touchDown. In the second case, stopToggling: probably needs to be called on any touchUp... event of the button.
- (void)startTimer {
pauseTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(doActions) userInfo:nil repeats:YES];
}
- (void) doActions {
theLabel.hidden != theLabel.hidden;
}
I have a countdown timer in my game and I'm trying to figure out how to make it so that it shows two decimal places and records with 2 decimal places in my table. Right now it counts down as a whole number and records as a whole number. Any ideas?
-(void)updateTimerLabel{
if(appDelegate.gameStateRunning == YES){
if(gameVarLevel==1){
timeSeconds = 100;
AllowResetTimer = NO;
}
timeSeconds--;
timerLabel.text=[NSString stringWithFormat:#"Time: %d", timeSeconds];
}
countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateTimerLabel) userInfo:nil repeats:YES];
To have sub-second updates, the timer's interval needs to be < 1. But the precision of NSTimer is just around 50 ms, so scheduledTimerWithTimeInterval:0.01 will not work.
Moreover, the timer can be delayed by various activities, so using timeSeconds will lead to inaccurate timing. The usual way is compare the NSDate now with the date when the timer starts. However, as this code is for a game, the current approach may cause less frustration to players esp. if the program or background processes consumes lots of resources.
The first thing to do is to convert the countdownTimer to sub-second interval.
countdownTimer = [NSTimer scheduledTimerWithTimeInterval:0.67 target:self selector:#selector(updateTimerLabel) userInfo:nil repeats:YES];
Then, don't count down the time by seconds, but centiseconds:
if(appDelegate.gameStateRunning == YES){
if(gameVarLevel==1){
timeCentiseconds = 10000;
AllowResetTimer = NO;
}
}
timeCentiseconds -= 67;
Finally, divide by 100 in the output:
timerLabel.text=[NSString stringWithFormat:#"Time: %d.%02d", timeCentiseconds/100, timeCentiseconds%100];
Alternatively, use a double:
double timeSeconds;
...
if(appDelegate.gameStateRunning == YES){
if(gameVarLevel==1){
timeSeconds = 100;
AllowResetTimer = NO;
}
}
timeSeconds -= 0.67;
timerLabel.text=[NSString stringWithFormat:#"Time: %.2g", timeSeconds];
I have an int which defines the objectAtIndex, which gives it to the string, which then displays it in the UILabel, HOWEVER, when I modify the array (add a word to it in this case) when I have the UILabel go through the array it only displays the odd ones. I have done an NSLog and found out that it DOES PASS EVERY SINGLE THING to the string, but the Label isn't displaying every single one, it only does it the first time, then I modify the array, and it only does odd
edit: the code:
- (void) stuff {
NSArray *indivwords = [sentence componentsSeparatedByString:#" "];
count = [indivwords count]; //count=int
if (i < count) {
NSString *chunk = [indivwords objectAtIndex:i];
[word setText:chunk];
NSLog(chunk);
i++;
} else {
word.textColor = [UIColor greenColor];
[word setText:#"DONE"];
}
}
All of this is being controlled by an NSTimer, which sets it off based on a slider value. Also i is set to 0 in the IBAction
The IBAction code:
word.textColor = [UIColor whiteColor];
[timer invalidate];
i = 0;
speedd = (1/speed.value)*60;
timer = [NSTimer scheduledTimerWithTimeInterval:(speedd) target:self selector:#selector(stuff) userInfo:nil repeats:YES];
EDIT:
I fixed it! What I did was call this after i reached the count
-(void)stoptimer
{
[timer invalidate];
timer = [NSTimer scheduledTimerWithTimeInterval:(.01) target:self selector:#selector(empty) userInfo:nil repeats:YES];
}
empty is just a void with nothing in it, well, all I did was add a comment,
//don't look over here, nothing to see here, oh look at that
Somebody can close this if they want
You said the time interval of your NSTimer is controlled by a slider. Perhaps you are starting a new timer instance every time you change the slider value, so after a change you would have two timers running. The first one updates the label and increments i. The second one comes right after the first and finds i's value incremented, so it displays the next chunk instead of the current one.
Count the instances of your timer - NSLog the timer in the timer callback and compare the results - it may be that you're firing more than one.
My guess is that you have two different actions calling this method, when you think there should be one. I'd put a break point in there, and see if it stops where you think it should.