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(st开发者_如何学GoartAutoRefresh) 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:
- First and formemost, I am at least least 90% positively sure that you don't want to call
[[NSRunLoop mainRunLoop] run]
in any of your program's methods — do those methods even exit, or do you keep aggregating thread upon thread? - Secondly, your timer invalidations are all a bit strange:
- There is no use in
if (timerRefresh) if ([timerRefresh isValid]) [timerRefresh invalidate];
; since in Objective C, messagingnil
is perfectly fine. The result of such a message is always0x0
, so the firstif
is unnecessary and the second one evaluates toNO
in that case, anyway. - Invalidating a timer means removing it from the runloop it was scheduled on. Hence, the second
if
is unnecessary, too — leaving you with just[timerRefresh invalidate];
. - For
-[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.
- There is no use in
- There is no difference between
[self performSelector:@selector(sendTeamNameClickToFunction:) withObject:sender]
and simply[self sendTeamNameClickToFunction:sender]
. Except that the latter is much easier to read ;-) - The
if
clauses 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:
-(void)pauseAndResumeTimer:(NSNotification *)notification
{
[timerRefresh performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:YES];
timerRefresh = nil;
NSNumber *result = [notification object];
if ([result boolValue]) return;
if ( !self.isConnectionAvailable || 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 mainRunLoop] addTimer:timerRefresh forMode:NSDefaultRunLoopMode];
}
精彩评论