I’ll go straight to the problem.
This ones eating my head since a week.
What i intend to do is set my timer, which is supposed to be fired on main run loop, from a secondary thread. So i do it as follows.
if(timerRefresh)
{
//[timerRefresh invalidate];
timerRefresh = nil;
}
if (!self.isConnectionAvailable) {
timerRefresh = [NSTimer timerWithTimeInterval:appDelegate.TimerInterval target:self selector:@selector(startAutoRefresh) userInfo:nil repeats:NO];
}
else if (self.isLivePresent||self.isUpcomingMatchToday) {
timerRefresh = [NSTimer timerWithTimeInterval:appDelegate.TimerInterval target:self selector:@selector(startAutoRefresh) userInfo:nil repeats:NO];
}
else {
timerRefresh = [NSTimer timerWithTimeInterval:LongRefresh target:self selector:@selector(startAutoRefresh) userInfo:nil repeats:NO];
}
NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
[runLoop addTimer:timerRefresh forMode:NSDefaultRunLoopMode];
[runLoop run];
When this fires, a loader begins loading on the main thread, and the processing work is done on the secondary thread.
I hope this is a correct way.
Now i have a child class within this main class which also has to show a loader while it triggers a filtering process, so to avoid multiple loaders, when the the filtering process triggers, i pause the refreshing on this parent class, by sending it notifications from the child class..like this…
-(void)teamNameClicked:(id)sender
{
BOOL result = YES;
NSNumber *newNumber = [NSNumber numberWithBool:result];
[[NSNotificationCenter defaultCenter] postNotificationName:@"PauseMatchesLiveMatchTimer" object:newNumber];
[self performSelector:@selector(sendTeamNameClickToFunction:) withObject:sender];
}
and when operation completes i have another notifier as this…
-(void)processTeamNameClick:(id)sender
{
UIButton *button = (UIButton *)sender;
selectedIndexDropDown = button.tag;
[self parseTeamFile:button.tag];
self.lblDropDown.text = [dictTeamFilter valueForKey:[NSString stringWithFormat:@"%i",button.tag]];
[tblResults performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
BOOL result = NO;
NSNumber *newNumber = [NSNumber numberWithBool:result];
[[NSNotificationCenter defaultCenter] postNotificationName:@"PauseMatchesLiveMatchTimer" object:newNumber];
}
Notice the YES and NO for results..
Now this is an observer for the notification…
-(void)pauseAndResumeTimer:(NSNotification *)notification;
{
NSNumber *newNumber = [notification object];
BOOL result = [newNumber boolValue];
if (result) {
if(timerRefresh)
{
if ([timerRefresh isValid])
[timerRefresh invalidate];
timerRefresh = nil;
}
}
else
{
if(timerRefresh)
{
if ([timerRefresh isValid])
[timerRefresh invalidate];
timerRefresh = nil;
}
if (!self.isConnectionAvailable) {
timerRefresh = [NSTimer timerWithTimeInterval:appDelegate.TimerInterval target:self selector:@selector(startAutoRefresh) userInfo:nil repeats:NO];
}
else if (self.isLivePresent||self.isUpcomingMatchToday) {
timerRefresh = [NSTimer timerWithTimeInterval:appDelegate.TimerInterval target:self selector:@selector(startAutoRefresh) userInfo:nil repeats:NO];
}
else {
timerRefresh = [NSTimer timerWithTimeInterval:LongRefresh target:self selector:@selector(startAutoRefresh) userInfo:nil repeats:NO];
}
NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
[runLoop addTimer:timerRefresh forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}
When the filtering process is on, i stop the parent timer. And when off i start it again.
Ok…So now the problem… When i do normal navigation on my pages, it works absolutely fine..like switching tabs, traversing between pages etc.
But if i use the filter process, somehow, it triggers my timer on the main page, and even when the view has disappeared, seems to kick off my timer event. I want to avoid that, but i just dont know how..
If anyone can genuinely help me, please do.
Thanks in advance.
There is some funny stuff going on in your code:
[[NSRunLoop mainRunLoop] run]in any of your program’s methods — do those methods even exit, or do you keep aggregating thread upon thread?if (timerRefresh) if ([timerRefresh isValid]) [timerRefresh invalidate];; since in Objective C, messagingnilis perfectly fine. The result of such a message is always0x0, so the firstifis unnecessary and the second one evaluates toNOin that case, anyway.ifis unnecessary, too — leaving you with just[timerRefresh invalidate];.-[NSTimer invalidate]to have an effect, it needs to be called on the thread the timer is scheduled on. From what I understood, this is not the case in all your methods. So you should useperformSelectorOnMainThread:withObject:waitUntilDone:with the appropriate arguments instead.[self performSelector:@selector(sendTeamNameClickToFunction:) withObject:sender]and simply[self sendTeamNameClickToFunction:sender]. Except that the latter is much easier to read 😉ifclauses inpauseAndResumeTimer:don’t make an awful lot of sense, i.e. there’s a lot of code duplication.Here is said method in a tidied-up fashion and with the invalidation happening on the main thread: