I've run various types of code to try and make a progress bar increment for x seconds and continue to do so even when in the background. Currently the bar just resumes from where it left off, via the timer, when going from background to focus.
How can I continue the timer even when the user minimizes the app?
Declare a NSTimer property in .h. Then call it from anywhere like :
self.nstimer= [NSTimer scheduledTimerWithTimeInterval:0.10 self selector:#selector(updateTime:) userInfo:nil repeats:YES];
And inside the method (audiocontroller is another class property):
- (void)updateTime:(NSTimer *)timer
{
// Progress bar value
progressView.progress = ((float)recievedData / (float) xpectedTotalSize);
}
It will continue call the method even the app is in background. You can cancel this method calling from applicationDidBecomeActive() method.
Related
I want my user to be able to tap a button and set a timer for a future date. If they tap the button multiple times I want to set multiple future events. What I have so far is this:
- (IBAction)setFutureButtonTapped:(id)sender {
NSTimer *futureTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:#selector(futureMethod) userInfo:nil repeats:NO];
}
This causes futureMethod to be called once in 30 seconds, however, if I press the button once, then again in 10 seconds, I would like future method to be called at time 30, and time 40. How do I achieve this?
The server that provides data to my app recently added a feature that allows you do to basic logging like "user selected logo" or "user is quitting".
The only place I'd like to use this is in a page with several sliders that does a calculation on the input values. This is continuous, it re-calculates the output as you move the sliders around.
Which leaves me the problem of when to call this logging method. I don't want to call it every time the numbers change, or I'll murder the server. I could put a "Calculate now" button, but that kills the entire mode-less UI I like.
Is there a way that I can coalesce calls so all the calls made within, say, 5 seconds, results in only one call to the work method? I'd also have to force the method to fire if the user does something else, like navigates away or quits the app.
You can easily add an NSTimer to the IBAction method you have for your slider. Every time that method is called, invalidate the timer and start it again. Put the analytics call in the timer's action method, which will only be called when the timer can actually complete.
For example:
#interface ViewController ()
#property (nonatomic) NSTimer *actionTimer;
#end
#implementation ViewController
- (IBAction)sliderChanged:(UISlider *)sender
{
[self.actionTimer invalidate];
NSLog(#"Slider value: %f", sender.value);
self.actionTimer = [NSTimer scheduledTimerWithTimeInterval:2
target:self
selector:#selector(timerCompleted)
userInfo:nil
repeats:NO];
}
- (void)timerCompleted
{
NSLog(#"Timer completed.");
}
#end
How about a background thread that observes the calculated value and fires an update by scheduling a block on a background thread when the output value is stable, like
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(showValue:)
name:#"showValue"
object:nil];
You can also schedule the block in viewWillDisappear for the leaving the view and (I think) quit events.
I am having a banners array and displaying it in my custom cell. When user clicks on banner, I push a detailViewController and opens in-app browser.
I am changing banners after every 5 seconds. For that, I am using NSTimer to schedule the selector call. Everything works great.... Until, user clicks on banner and come back from detailViewController. When user comes back, NSTimer behaves really weird. It changes first banner after 5 seconds (as assigned) and then next banner is changed after 1 second and so on.
Her is the code I am using:
#pragma mark - User Methods
-(void) resetBannerRotationTimer {
[self.bannerTimer invalidate];
self.bannerTimer = nil;
self.timeInterval = 5.0f;
self.bannerTimer = [NSTimer scheduledTimerWithTimeInterval:self.timeInterval target:self selector:#selector(rotateBanner) userInfo:nil repeats:YES];
self.timeInterval = self.bannerTimer.timeInterval;
[[NSRunLoop currentRunLoop] addTimer:self.bannerTimer forMode:NSRunLoopCommonModes];
}
rotateBanner:
-(void) rotateBanner {
BannerCell *bannerCell = (BannerCell *)[self.dealsTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
[bannerCell updateBanner];
}
In my updateBanner method, I am handeling UIPageControl to change pages. (I don't think that code needs to be posted).
I am calling resetBannerRotationTimer method in viewWillAppear method.
i think you are missing to fire your timer
add this line after timer scheduling
[self.bannerTimer fire];
I one of my ViewController I want to call a method updateVisitotsLists on some time criteria's and am not able to decide which way will be best to achieve it.
1) Every time the view is loaded/appeared I want to call this method.
For this in viewDidAppear method I can call this before calling [super viewDidAppear];, so that works, I believe.
2) If user is on this view only, then I want to call this method after every 5 secs.
For this, I need to set a NSTimer. I want to stop this timer when viewDidDisappear - as don't want it running unnecessary. Should I use an UnScheduled Timer as shown here and start and stop in appear & disappear methods ? In viewDidAppear, initially I call this method, and then also set
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 5.0
target: self
selector:#selector(updateVisitotsLists:)
userInfo: nil repeats:NO];
What will be the best way and methodology to achieve what I am looking for ? Any help is highly appreciated.
Thanks.
UPDATED :-
#Lord Zolt, as per your comment I did the following :-
//In .h
#property (strong, nonatomic) NSTimer *timer;
// .m
#synthesize timer;
- (void)viewDidLoad
{
........
[super viewDidLoad];
// CREATE TIMER
timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:#selector(onTimerCall:) userInfo:nil repeats:YES];
}
-(void) viewWillDisappear:(BOOL)animated {
[timer invalidate];
timer = nil;
[super viewWillDisappear:animated];
}
-(void) onTimerCall: (NSTimer *) _timer {
// UPDATE VISITOR'S LIST
[self updateVisitotsLists];
}
Is this proper ?
I would recommend using timers.
Create an NSTimer property, but I would recommend calling invalidate on them on viewWillDisappear.
If you don't call invalidate, when the view controller is dismissed or popped, it won't be deallocated, since NSTimer will keep it alive.
The code you posted is fine with a few modifications:
You don't need to #synthesize properties anymore (unless you overwrite both the setter and getter).
Don't set timer to nil.
Edit: If you want the timer to be related to the screen (aka it should be executed only when the screen is visible), you should initialise in viewDid(Will)Appear and stop it in viewDid(Will)Disappear.
I'm working with all UIKit, and—for prototyping purposes have just shoved all the logic into the main viewController. I create some UIViews in viewDidLoad, hide some, and then set an NStimer to unhide the hidden ones in 4 seconds. This timer fires perfectly in the simulator, but will never fire on the iPad. Why could this happen and what should I even be looking for?
This is where I set my view and timer.
- (void)viewDidLoad {
[super viewDidLoad];
//snipped out long code that adds UIViews as subviews and runs fine
curtainView.hidden=YES;
questionLabel.hidden=YES;
[NSTimer scheduledTimerWithTimeInterval:4
target:self
selector:#selector(dropCurtain:)
userInfo:nil
repeats:NO];
[NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:#selector(askQuestion:)
userInfo:nil
repeats:NO];
}
And here's the function that gets called when the first timer is up. This doesn't run on the iPad.
-(void)dropCurtain:(NSTimer *)timer{
curtainView.hidden=NO;
//curtainView.alpha=.5;
[self.view bringSubviewToFront:curtainView];
[self.view bringSubviewToFront:triesLabel];
}
Your callback might be called not in the main thread, ui changes call only works from the main thread. If this is the case there's a method of nsobject to schedule a call to selector in the main thread, and you can call this from your callback to manipulate ui
(sorry not near my work computer)