开发者

NSTimer Uniqe question

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:
    1. There is no use in if (timerRefresh) if ([timerRefresh isValid]) [timerRefresh invalidate];; since in Objective C, messaging nil is perfectly fine. The result of such a message is always 0x0, so the first if is unnecessary and the second one evaluates to NO in that case, anyway.
    2. 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];.
    3. 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 use performSelectorOnMainThread:withObject:waitUntilDone: with the appropriate arguments instead.
  • 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 in pauseAndResumeTimer: 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];
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜