Refreshing data from server using NSTimer - ios

i want to refresh the data from the server ,but that refreshing time-> i want to get that from the user and pass to the timer ,how can i do this i know to give the value like,
self.timerCounter =[NSTimer scheduledTimerWithTimeInterval:300.0
target:self selector:#selector(getGraphData) userInfo:nil repeats:YES];
i also tried using protocols and delegates like ,
self.timerCounter =[NSTimer scheduledTimerWithTimeInterval:strTime
target:self selector:#selector(getGraphData) userInfo:nil repeats:YES];
but i got error like
Sending NSString _strong to parameter of incompatible type
NSTimerInterval
now ,i want to get that from the user in the textfield ,please help me to do this

I think there is the problem in converting strTime to NSTimeInterval.
self.timerCounter =[NSTimer scheduledTimerWithTimeInterval:[strTime doubleValue] target:self selector:#selector(getGraphData) userInfo:nil repeats:YES];
Try this, This should work if there is conversion problem..

Convert textfield.text to NSTimeInterval
Try like,
let strTime : NSTimeInterval = NSTimeInterval(textfield.text)!

You are using NSString instead of a NSTimeInterval type data. You should be able to resolve this by converting your txtTime or strTime to a double value.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *url = [defaults objectForKey:#"server_url"];
NSString *txtTime = [defaults objectForKey:#"refresh_time"];
if (txtTime != nil) {
NSTimeInterval timeInterval = [txtTime doubleValue];
self.timerCounter = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:#selector(getGraphData) userInfo:nil repeats:true];
}

Related

How to start a timer from zero in iOS

I have a button on which i have placed a UITapGestureRecognizer. When i tap on that button, i call a method that starts the time.
My question is, i am able to get the timer string on a label. But the timer starts from current date-time, and i want to start the timer always from zero(like a countdown timer). Here below is my code for timer.
-(IBAction)micPressed{
if (gestureRecognizer.state==UIGestureRecognizerStateBegan) {
gestureRecognizer.view.alpha=0.2f;
[label setHidden:NO];
if (!_timer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.1f
target:self
selector:#selector(_timerFired:)
userInfo:nil
repeats:YES];
}
}
else{
[label setHidden:YES];
gestureRecognizer.view.alpha=10.2f;
if ([_timer isValid]) {
[_timer invalidate];
}
_timer = nil;
}
}
- (void)_timerFired:(NSTimer *)timer {
NSDateFormatter *dateformatter=[[NSDateFormatter alloc]init];
[dateformatter setDateFormat:#"mm:ss:SSS"];
NSString *dateInStringFormated=[dateformatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:0]];
NSLog(#"%#",dateInStringFormated);
[label setText:dateInStringFormated];
}
Please can anyone suggest me the solution. Any help is appreciated.
Your code should be like,
NSDateFormatter *dateformatter=[[NSDateFormatter alloc]init];
[dateformatter setDateFormat:#"mm:ss:SSS"];
NSString *dateInStringFormated=[dateformatter stringFromDate:[dateformatter dateFromString:#"00:00:000"]];
NSLog(#"test : %#",dateInStringFormated);
I have just chage [NSDate dateWithTimeIntervalSinceNow:0] with [dateformatter dateFromString:#"00:00:000"].
It will start with zero always.
Update :
I think you want something like timer that update minutes,seconds and milliseconds as i understand your question now. You can achieve it something like,
Schedule timer like,
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
Now your updateTimer should be like,
-(void)updateTimer{
static double counter = 0;
static int counter2 = 0;
int seconds = (int)counter % 60;
int minutes = ((int)counter / 60) % 60;
NSLog(#"%02d:%02d:%03d",minutes,seconds,counter2); // This should be your labels text that updating continuously
counter = counter + 0.01;
counter2++;
if (counter2 == 100) {
counter2 = 0;
}
}
Hope this will help :)
The problem is you are starting your timer from current time itself. To make a like countdown timer. You need to do the following:
Take an int named Counter and intialize it from 0
Fire your NSTimer and at that time increase the counter
Display the counter value in the UILabel text.
Once your NSTimer stops, again make it to 0.
That's it! This is how you can achieve the desired result.
Code:
int counter = 0;
- (void)_timerFired:(NSTimer *)timer {
counter++;
}
Once NSTimer is invalidate again make it to counter = 0
Remember the time when you have started the timer:
_startDate = [NSDate date];
_Timer = ...
Then use the time interval since the start date in your _timerFired method:
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
NSString *dateInStringFormatted = [formatter stringFromTimeInterval:[[NSDate date] timeIntervalSinceDate:_startDate]];

Display Text Word by Word on iOS

(I recognize that this is a duplicate of another question of mine, but that was put on hold, and when I reworked the question I was instructed to post it as a new question as none of the answers there could solve my request.)
I have a request that I think should be fairly easy to accomplish, but I cannot find the solution anywhere.
Say I have a string with about a paragraph or so of text. I want to display that text on a UITextView, but in a special way. I want the words to print out one by one, kind of like how you see in the movies on old computer terminals.
I do not have trouble splitting the string, that is OK, but the trouble is I cannot print out the individuals strings to my textView one by one. The UItextView is called self.textView. My code is as follows:
for (int wordIndex = 0; wordIndex < [wordList count]; wordIndex++) {
//[self.textView setText: [NSString stringWithFormat:#"%# %#",self.textView.text, [wordList objectAtIndex:wordIndex]]];
NSString *newText = [NSString stringWithFormat:#"%#", [wordList objectAtIndex:wordIndex]];
fullString = [NSString stringWithFormat:#"%# %#",fullString, newText];
[self.textView performSelector:#selector(setText:) withObject:fullString afterDelay:.9];
}
Where fullString is a global variable. Wordlist is an NSArray of my words (as strings).
If you need further clarification, then please do not hesitate to ask. Thanks so much!
Rather than trying to do everything in a loop, I suggest setting up a repeating NSTimer and adding a new word to your text view each time it fires. That gives you better control of the timing of updates and gives the UI a chance to display the result before the next iteration. When the last word has been shown, invalidate the timer.
Using answers from #Phillip Mills and #Ashish Kakkad I have figured this out. Here is my code (I cannot get to to format correctly, so if someone could edit it for me that would be awesome):
- (void) startTimer {
if ( self.wordtimer == nil ) {
self.wordtimer = [NSTimer scheduledTimerWithTimeInterval: 0.1
target: self
selector: #selector(printWords)
userInfo: nil
repeats: YES];
}
}
- (void) stopTimer {
if ( self.wordtimer || [self.wordtimer isValid])
{
[self.wordtimer invalidate];
self.wordtimer = nil;
}
}
-(void)printWords {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
Element *tempElement = [[Element alloc] init];
tempElement = [self.elementsArray objectAtIndex:appDelegate.currentElement];
NSArray *wordList = [tempElement.text componentsSeparatedByString:#" "];
if(wordIndex < [wordList count]){
[self.textView setText: [NSString stringWithFormat:#"%# %#",self.textView.text, [wordList objectAtIndex:wordIndex]]];
wordIndex++;
[self resetTextAndFont];
[self.textView setFont:[UIFont fontWithName:#"HelveticaNeue-Medium" size:15]];
NSLog(#"Timer Fired!");
}
else {
//[self.wordtimer invalidate];
[self stopTimer];
NSLog(#"Timer quit.");
[self resetTextAndFont];
[self.textView setFont:[UIFont fontWithName:#"HelveticaNeue-Medium" size:15]];
wordIndex = 0;
}
}
Whenever I want to fire the animation I just clear the textView's text and call [self startTimer] and to invalidate it I just call [self stopTimer]. Wordindex is a global integer.
For displaying the word by word, you need to first split the sentence in a space character using componentsSeparatedByCharactersInSet and it will return an array then the same you need to extract in a delay manner after that you can append the string in your UITexyView which can be done by using NSTimer and like that below:-
//Below for delaying use the timer
- (void)viewDidLoad
{
[super viewDidLoad];
timer=[NSTimer scheduledTimerWithTimeInterval:3 target:self selector:#selector(startTimer) userInfo:nil repeats:YES];
}
//Below is the timer method
-(void)startTimer
{
//Assuming some string
NSString *str=#"This is testing";
//Splitting the sentence by space character
NSArray *arr=[str componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
//len is integer which is a counter for iteration of array.
if (len<arr.count)
{
//Appending word by word
[[self.textView textStorage] appendAttributedString:[[NSAttributedString alloc]initWithString:arr[len]]];
[[self.textView textStorage] appendAttributedString:[[NSAttributedString alloc]initWithString:#" "]];
len++;
}
else
{
[timer invalidate];
return;
}
}
Take global to class string and int variable say string is fullString and int variable is wordIndex. Use NSTimer or delay to invoke custom method. In that method put check like
if(wordIndex < [wordList count]){
NSString *newText = [NSString stringWithFormat:#"%#", [wordList objectAtIndex:wordIndex]];
// increment the global int variable by one i.e.wordIndex++
// append this string to exsting string
// set appended text to textview...
}

How to Create a count up timer in iOS

I have this code:
NSDate *now = [NSDate date];
static NSDateFormatter *dateFormatter;
if (!dateFormatter) {
dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"h:mm:ss";
}
recordStatusLabel.text = [dateFormatter stringFromDate:now];
NSLog(#"Time now: %#", [dateFormatter stringFromDate:now]);
that counts the current time. How can i change it to start in this format?
00:00:00 (hours:minutes:seconds)
from a NSString variable:
Example: i got this value for my variable
NSString * time = #"02:16:23";
then the counter will continue the count to:
02:16:24
.
.
.
02:20:13
Create an instance of NSTimer class and set time for event fire 1 second with repeat option YES. In the event handling update your label with current time. When your functionality is complete, invalidate the timer to stop firing events.
Here is the code to create instance of NSTimer class:
NSTimer *countUpTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
selector:#selector(countUpTimerFired:) userInfo:nil repeats:YES];
Here is the method for event handling:
- (void)countUpTimerFired:(id)sender {
dispatch_async(dispatch_get_main_queue(), ^{
recordStatusLabel.text = [dateFormatter stringFromDate:[NSDate date]];
});
}
Keep of dateFormatter and countUpTimer as class variables.
This is the simple approach to achieve your required functionality as you are starting your time from current device time; So you won't be requiring extra efforts to get value from label, incrementing the value and then converting back to string.
EDIT:
If you want to start the counter from anyother time value or from a string, you can keep a integer variable to keep the value of time in seconds. Then increment the value when timer event gets called (every second) and then converting that integer to time string.
Here's the code for initial value:
NSString *timeString = recordStatusLabel.text; //contains a string in time format like #"2:16:23" or #"00:00:00" or current time or any other value.
NSArray *timeComponents = [timeString componentsSeparatedByString:#":"];
int timeInSeconds = [timeComponents[0] intValue]*3600 + [timeComponents[1] intValue]*60 + [timeComponents[2] intValue];
in the event handling of timer:
- (void)countUpTimerFired:(id)sender {
timeInSeconds++;
int hours = timeInSeconds/3600;
int minutes = (timeInSeconds%3600)/60;
int seconds = timeInSeconds%60;
dispatch_async(dispatch_get_main_queue(), ^{
[recordStatusLabel setText:[NSString stringWithFormat:#"%d:%02d:%02d", hours, minutes, seconds]];
});
}
Since you are dealing with a timer which the fastest value is the second, then to achieve performance you just fire a timer which repeats every second.
Declare your instance variables
#implementation Yourclass {
NSDate *startDate;
NSTimer *yourTimer;
NSString *myTime;
}
When you click a button to start timer
-(IBAction)startTimer:(id)sender {
startDate = [NSDate date];
yourTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timeHandler:) userInfo:nil repeats:YES];
[yourTimer fire];
}
Implement your method which is the handler method of timer
-(void)timeHandler:(NSTimer *)myTimer {
//Difference between dates in seconds
NSTimeInterval elapsedTime = [startDate timeIntervalSinceNow];
//Divide by 3600 to get the hours
NSInteger hours = elapsedTime/3600;
//Divide by 60 to get the minutes
NSInteger minutes = elapsedTime/60;
NSInteger seconds = elapsedTime;
myTime = [NSString stringWithFormat:#"%i:%i:%i",hours, minutes, seconds];
// update the label
recordStatusLabel.text = myTime;
}

Invalidating instanced NSTimers

I have a UIScrollView which is being populated by UILabels which are being updated by NSTimers on each page which is being populated by an NSDictionary
for (id key in _infoDict) {
NSTimer *releaseDateTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self
selector: #selector(calculateReleaseDate:) userInfo: dateInfo repeats: YES];
[self.releaseDateTimer fire];
}
The UILabels which are being refreshed are all referenced by their tags which are based on which page they are on and which calendar unit.
-(void)calculateReleaseDate:(NSTimer*)theTimer {
NSString *monthString = [[NSString alloc]initWithFormat:#"%i",[finalDate month]];
NSString *dayString = [[NSString alloc]initWithFormat:#"%i",[finalDate day]];
NSString *hourString = [[NSString alloc]initWithFormat:#"%i",[finalDate hour]];
NSString *minutesString = [[NSString alloc]initWithFormat:#"%i",[finalDate minute]];
NSString *secondsString = [[NSString alloc]initWithFormat:#"%i",[finalDate second]];
UILabel *monthValue = (UILabel*)[self.scrollView viewWithTag:[monthTag intValue]];
[monthValue setText:monthString];
UILabel *dayValue = (UILabel*)[self.scrollView viewWithTag:[dayTag intValue]];
[dayValue setText:dayString];
UILabel *hourValue = (UILabel*)[self.scrollView viewWithTag:[hourTag intValue]];
[hourValue setText:hourString];
UILabel *minValue = (UILabel*)[self.scrollView viewWithTag:[minTag intValue]];
[minValue setText:minutesString];
UILabel *secValue = (UILabel*)[self.scrollView viewWithTag:[secTag intValue]];
[secValue setText:secondsString];
}
This isn't the complete method but you get the idea.
Now at some point I want to rebuild the entire page by removing all the UIScrollView subviews and then repopulating it.
This is where my problem is coming in is that my labels values are jumping between numbers.
I can only assume that there are still instances of my previously created timers are still accessing these labels as well.
Is there a way to access the timers on the runloop and running [NSTimer invalidate]; on them or am I going about this all wrong.
Any input would be appreciated.
You can add your NSTimer instances in a NSMutableArray in your for loop. Then, you can invalidate them if they are still valid in another for loop. You can use isValid method to check if NSTimer is still valid.

Format NSTimeInterval as Minutes:Seconds:milliseconds

Can anyone please tell me how to display milliseconds in this piece of code?
-(void)updateViewForPlayerInfo:(AVAudioPlayer*)p {
countdownTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(updateTimeLeft)userInfo:p repeats:YES];
}
- (void)updateTimeLeft {
NSTimeInterval timeLeft = player.duration - player.currentTime;
int min=timeLeft / 60;
int sec=lroundf(timeLeft) % 60;
durationLabel.text = [NSString stringWithFormat:#"-%02d:%02d",min,sec,nil];
}
[NSTimer scheduledTimerWithTimeInterval:0.0167 target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
-(void)updateTimer {
countDownTotalTimer++;
TotalTime.text=[self timeFormatted:countDownTotalTimer];
}
- (NSString *)timeFormatted:(int)milli
{
int millisec = ((milli) % 60)+39;
int sec = (milli / 60) % 60;
int min = milli / 3600;
return [NSString stringWithFormat:#"%02d:%02d:%02d",min, sec, millisec];
}
If any wants milliseconds to max 60 than edit this line
int millisec = ((milli) % 60)+39;
to
int millisec = ((milli) % 60);
I don't understand. Don't you just have to create a new variable for the milliseconds?
NSInteger milliseconds = (sec * 1000);
durationLabel.text = [NSString stringWithFormat:#"-%02d:%02d.%04d",min,sec, milliseconds, nil];
I think this is the simplest solution:
durationLabel.text = [NSString stringWithFormat:#"-%02d:%06.3f",
(int)(timeLeft / 60), fmod(timeLeft, 60)];
That formats the time as MM:SS.sss. If you really want it as MM:SS:sss (which I don't recommend), you can do this:
durationLabel.text = [NSString stringWithFormat:#"-%02d:%02d:%03.0f",
(int)(timeLeft / 60), (int)fmod(timeLeft, 60), 1000*fmod(timeLeft, 1)];
Note that stringWithFormat: does not require nil at the end of its argument list.

Resources