NSTimer does not call selector after assigned time interval. iOS - ios

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

Related

UIProgressView paused progressing when user is scrolling UITableView in iOS

In UIView I have taken one UIProgressView to show the Progress of the data downloaded from the server and to show those data I have taken an UITableView. The web service is via Polling, so which data is loading, I am loading it into an UITableView. But when user is scrolling the UITableView the ProgressBar paused its progress, but when again I am stopping my manual scroll of UITableView that time again the Progress bar is starting its progress from last paused position.
Code which I have Written:
Taken an outlet:
IBOutlet UIProgressView *pgrsVw;
When I am starting my web service call:
pgrsVw.progress = 0.0;
pgrsVw.hidden=false;
[self performSelectorOnMainThread:#selector(makeMyProgressBarMoving) withObject:nil waitUntilDone:NO];
Now to show the Progress:
- (void)makeMyProgressBarMoving
{
float actual = [pgrsVw progress];
if (actual < 1)
{
pgrsVw.progress = actual + PROGRESSOFDATA;
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(makeMyProgressBarMoving) userInfo:nil repeats:NO];
}
else
{
pgrsVw.progress=1.0;
pgrsVw.hidden=true;
}
}
Now when the data downloading is completed:
pgrsVw.progress=1.0;
I have just changed my timer code, Now it is working fine. That mean when data is loading in background, the progress bar is also moving when user is scrolling the tableview.
Changed code:
NSTimer *timer = [NSTimer timerWithTimeInterval:0.10 target:self selector:#selector(makeMyProgressBarMoving) userInfo:nil repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

How to repeate NSTimer every day at particular time in iOS app

I have method which call the sqlite method to get data and then display count to application badge number in ip. I want that the method should be called every day at 12.5 am so that it has new count for the day. I am doing in following way:
[NSTimer scheduledTimerWithTimeInterval:300 target:self selector:#selector(makeNotificationRequest:) userInfo:nil repeats:YES];
I am calling this NSTimer in when application goes in background state.
-(void)makeNotificationRequest:(NSTimer *)timer {
[self repeatedMethod];
}
- (void)repeatedMethod {
SOWObject *object =[[SOWObject alloc]init];
[object getBadgeNumber:[self getDBPath]];
[UIApplication sharedApplication].applicationIconBadgeNumber=badgeArray.count;
}

Appropriate way to call and cancel a selector in Objective-c?

So I have an app that when a user touches a certain object, I kick-off a selector via delay. I am not sure I want or need the delay, but am not sure of best practice, maybe a queue? Anyway, here is what I need, regardless of what I have now.
WHAT I HAVE NOW
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(doSomething) object:self];
[self performSelector:#selector(doSomething) withObject:nil afterDelay:2.0];
When the user touches a certain object I need to kick-off a method, but if he/she touches the object again, I want to not call the method.
Use case #1:
User touches object
User does nothing for 2 seconds
Call selector
Use case #2:
User touches object then
User touches object .5 seconds later (so cancel selector call)
User touches object .3 seconds later (so cancel selector call)
User touches object .9 seconds later (so cancel selector call)
User doesn't touch anything for 2 seconds
Call selector
If feel like performSelector and cancelPrevious are hacky. Should I be using some sort of queue and then clearing out the queue every time the user touches again?
Or should I use a timer and just restart the timer each time the user touches it?
I wrote something quick, hopefully it'll help. Every time start is hit the timer resets
#interface ViewController ()
{
NSTimer *timer;
NSInteger seconds;
}
#end
- (IBAction)start:(id)sender
{
seconds = 5;
[timer invalidate];
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(execute) userInfo:nil repeats:YES];
}
- (void)execute
{
if(seconds > 0) {
NSLog(#"seconds: %li", (long)seconds);
seconds--;
}
else {
NSLog(#"fire");
[timer invalidate];
}
}

how to invalidate NSTimer?

self.timerProgress=[NSTimer scheduledTimerWithTimeInterval:50.0 target:self selector:#selector(stopProgressView) userInfo:nil repeats:NO];
-(void)stopProgressView
{
if ([self.timerProgress isValid]) {
[self.timerProgress invalidate];
self.timerProgress=nil;
}
}
and on a button click when i tried to invalidate NSTimer object
-(void)cancelTimer
{
if ([self.timerProgress isValid]) {
[self.timerProgress invalidate];
self.timerProgress=nil;
}
}
it don't get invalidate. It calls once stopProgressView after the interval of 50.
How to get resolve from this issue?
- (IBAction)stopTimer {
if ([timerProgress isValid]) {
[timerProgress invalidate];
}
}
Don't use self.timerProgress use just timerProgress
The most likely reason for this is that your timer scheduled on a different run loop to the one where you try and invalidate it.
Timers must be invalidated on the same thread/runloop as the run loop that they are scheduled on.
Cocoa touch isn't thread safe, so you should be running all UI related activities on the main thread. It may work if you do GUI work on different threads, but then you'll get random crashes, and you'll also generate timer problems like this.
It seems like from what you're posting it should work. This is how I have it in my apps and it works fine.
However, you could try making the selector one that takes a timer object like:
-(void)stopProgressView:(NSTimer *)timer{
//do stuff with timer here
}
Note that this would also mean that you should change #selector(stopProgressView) to #selector(stopProgressView:). Although for the record my current stop timer function just uses [self.timer invalidate] and it works fine.
My other piece of advice for debugging is to use NSLogs to make sure each of the methods are in fact getting called, and that when the method is called an NSLog within the if clause to make sure that works.
You create NSTimer with out NSRunLoop so your NSTimer not started, to add this code after
self.timerProgress = [NSTimer scheduledTimerWithTimeInterval:50.0
target:self
selector:#selector(stopProgressView)
userInfo:nil
repeats:NO];
//add
[[NSRunLoop currentRunLoop] addTimer:_tapTimer
forMode:NSDefaultRunLoopMode];

Why would my timer work on the iPad simulator but not on the iPad?

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)

Resources