NSTimer在无效时不会停止

时间:2014-06-27 10:26:42

标签: ios iphone xcode nstimer

我想检查应用程序是否处于空闲状态(用户在过去30分钟内未采取任何操作)并注销用户。

为此,我有一个重置计时器的事件管理器。

- (void)sendEvent:(UIEvent *)event {      
    if(event == nil) {
        [self resetIdleTimer];
    } else {
        [super sendEvent:event];

        // Only want to reset the timer on a Began touch or an Ended touch, to reduce the number of timer resets.
        NSSet *allTouches = [event allTouches];
        if ([allTouches count] > 0) {
            // allTouches count only ever seems to be 1, so anyObject works here.
            UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
            if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded)
                [self resetIdleTimer];
        }
    }
}

- (void)resetIdleTimer {
    if (self.idleTimer) {
        [self.idleTimer invalidate];
        self.idleTimer = nil;
    }

    NSInteger maxTime = 60*30; //30 minutes

    self.idleTimer = [NSTimer scheduledTimerWithTimeInterval:maxTime target:self selector:@selector(checkIfIdleTimerExceeded) userInfo:nil repeats:NO];
}
- (void)checkIfIdleTimerExceeded {

    theProfileManager = [[ProfileManager alloc] init];
    theProfile = [theProfileManager getProfile];

    if( ! [[theProfile getStatus]isEqualToString:@"u1"]) {
        if( ! [[theProfile getTheUser] isUnlimitedLogin]) {
            theProfile = nil;
            theUserManager = [[UserManager alloc] init];
            [theUserManager setCurrentUser:[theProfile getTheUser]];
            [theUserManager setCurrentUserAccount:[[theProfile getTheUser] getTheUserAccount]];
            [theUserManager setCurrentUserSettings:[[theProfile getTheUser] getTheUserSettings]];
            [theUserManager logoutCurrentUser];

            [[MenuItemDataManager alloc] deleteJsonData];

            NSNotification *msg = [NSNotification notificationWithName:@"leftPanelMsg" object:[[NSString alloc] initWithFormat:@"Home"]];
            [[NSNotificationCenter defaultCenter] postNotification:msg];

            [self performSelector:@selector(loadHomeView:) withObject:nil afterDelay:0.5f];
        }
    }
    [self resetIdleTimer];

}

checkIfIdleTimerExceeded执行注销过程。

问题: 15分钟后,我触摸屏幕,调用resetIdleTime并重新启动新的NSTimer。但是15分钟后,应用程序会将用户注销。

感谢您的帮助。

安德烈。

2 个答案:

答案 0 :(得分:1)

根据您对Touches活动的要求。你应该这样做:

 NSSet *allTouchEvents = [event allTouches];
    if ([allTouchEvents count] > 0) {
        // allTouchEvents count only ever seems to be 1, so anyObject works here.
        UITouchPhase phase = ((UITouch *)[allTouchEvents anyObject]).phase;
        if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded)
            [self resetIdleTimer];
    }

在resetIdleTimer中,

self.idleTimer = [NSTimer scheduledTimerWithTimeInterval:maxTime target:self selector:@selector(checkIfIdleTimerExceeded) userInfo:nil repeats:NO];

应该像

self.idleTimer  = [NSTimer scheduledTimerWithTimeInterval:maxTime target:self selector:@selector(checkIfIdleTimerExceeded:) userInfo:nil repeats:NO]; 

checkIfIdleTimerExceeded应该是这样的:

-(void) checkIfIdleTimerExceeded :(NSTimer*)timer
    {

       //Do your all process and invalidate after completion

        [timer invalidate];

    }

答案 1 :(得分:0)

当您触摸屏幕时,我不确定您工作流程中的–resetIdleTimer旁边可以调用哪种其他方法,但该解决方案对我有用,因为您已经说过要让它工作:

我在日志控制台中看到如果我在7秒内点击一个按钮就会调用–resetTimer:,它会正确地重置计时器并创建一个新的7秒计时器。

只有当我在7秒内没有触摸屏幕上的按钮时,注销方法才会调用,并且计时器最终会调用–logout:方法。

- (void)resetTimer:(NSTimer *)timer {
    NSLog(@"reset time...");

    if (timer.isValid) [timer invalidate], _timer = nil;
    _timer = [NSTimer scheduledTimerWithTimeInterval:7.f target:self selector:@selector(logout:) userInfo:nil repeats:NO];
}

//

- (void)buttonTouchedUpInside:(UIButton *)sender {
    NSLog(@"touched...");

    [self resetTimer:_timer];
}

//

- (void)logout:(NSTimer *)timer {
    NSLog(@"logout...");

    if (timer.isValid) [timer invalidate], _timer = nil;

    // logout ...
}