我有超时功能,如果应用程序空闲(在后台)一段时间,我会暂停我的应用并将用户发送到登录屏幕。我在我的应用程序委托中将用户默认值中的“timedOut”键设置为YES,然后在每个视图控制器中引用该键,如果是,则转到登录屏幕。在登录屏幕上,如果“timedOut”为YES,我有一个标签显示“Session has timed out”。我的问题是,如果我登录,然后很快注销,标签就会显示,即使我在显示标签后立即将该键显式设置为NO,然后同步用户默认值。 如果我等待一两秒并退出,标签就会隐藏起来。我已经解决了“问题”,但想了解这种行为。
来自视图的代码确实在我的登录视图控制器中加载。您会认为这会将isTimedOut更改为NO,但是当我快速注销时,再次调用viewdidload,但isTimedOut为YES。
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
sessionLabel.hidden = YES;
isTimedOut = [defaults boolForKey:@"isTimedOut"];
if (isTimedOut == YES)
{
sessionLabel.hidden = NO;
defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:NO forKey:@"isTimedOut"];
isTimedOut = NO;
NSLog(@"Timed Out has been reset to %s",[defaults boolForKey:@"isTimedOut"] ? "YES" : "NO");
[defaults synchronize];
}
更新
我使用app app delegate中的属性而不是NSUserDefaults替换了上面的代码,并且“奇怪”的行为消失了。
eONavAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
isTimedOut = appDelegate.isTimedOut;
sessionLabel.hidden = YES;
//isTimedOut = [defaults boolForKey:@"isTimedOut"];
NSLog(@"Timed Out has been reset to %s",appDelegate.isTimedOut ? "YES" : "NO");
if (isTimedOut == YES)
{
appDelegate.isTimedOut = NO;
sessionLabel.hidden = NO;
}
更多代码
要注销,我让UIButtonBarItem以编程方式调用segue。 doLogout属性告诉登录视图控制器运行注销API。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:@"logoutSegue"])
{
// Get reference to the destination view controller
eoLoginViewController *vc = [segue destinationViewController];
vc.doLogout = YES;
}
}
isTimedOut设置在app delegate中的一个位置。
-(void)timeoutWithDate:(NSDate *)currentDate
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDate *previousDate = [defaults objectForKey:@"enteredBackground"];
NSTimeInterval distanceBetweenDates = [currentDate timeIntervalSinceDate:previousDate];//TimeInterval is in seconds
NSLog(@"Time between dates in seconds %f",distanceBetweenDates);
double minutesInAnHour = 60;
double minutesBetweenDates = distanceBetweenDates / minutesInAnHour;
NSLog(@"minutesBetweenDates %f",minutesBetweenDates);
if(minutesBetweenDates > 60)
{
isTimedOut = YES;
}
else
{
isTimedOut = NO;
}
}
答案 0 :(得分:2)
使用此:
保存Bool:
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isTimedOut"];
加载Bool:
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"isTimedOut"] == YES) {
//it equals yes
}
else {
//it equals no
}
答案 1 :(得分:2)
你为什么不尝试这样的事情?我没有看到你的完整项目,但它应该像魅力一样。
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
...然后
- (void)applicationWillResignActive:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults] setValue:[NSDate date] forKey:@"sleepTime"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
和...
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSInteger _timeoutInSeconds = 300;
NSDate *_sleepTime = [[NSUserDefaults standardUserDefaults] valueForKey:@"sleepTime"];
if (_sleepTime) {
NSCalendar *_calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *_dateComponents = [_calendar components:NSSecondCalendarUnit fromDate:_sleepTime toDate:[NSDate date] options:0];
if (_dateComponents.second > _timeoutInSeconds) {
// expired session
} else {
// valid session
}
}
}