如何在iOS应用程序中添加基于用户交互(或缺少交互)的计时器?换句话说,如果2分钟内没有用户交互,我想让应用程序做点什么,在本例中导航到初始视图控制器。如果在1:55有人触摸屏幕,计时器将重置。我认为这需要一个全局计时器,所以无论你在哪个视图上,缺少交互都会启动计时器。不过,我可以在每个视图上创建一个唯一的计时器。是否有人有任何建议、链接或示例代码,这些都是以前做过的
Anne提供的链接是一个很好的起点,但由于我是n00b,很难将其转化为我现有的项目。我发现一个博客[原来的博客不再存在]提供了更好的一步一步,但它不是为XCode 4.2和使用故事板编写的。下面是我如何让非活动计时器为我的应用程序工作的总结:
-
创建一个新文件->Objective-C类->键入一个名称(在我的例子中是TIMERUIApplication),并将子类更改为UIApplication。您可能需要在subclass字段中手动键入此项。您现在应该拥有相应的.h和.m文件
-
将.h文件更改为如下所示:
#导入<;基础/基础h>; //应用程序“超时”之前的时间长度。这个数字实际上代表秒,所以我们必须在.m文件中将它乘以60 #定义KapplicationTimeOutingMinutes 5 //AppDelegate需要注意的通知,以便知道它确实已“超时” #定义[email protected]“AppTimeOut” @接口应用程序:UIApplication { NSTimer*myidleTimer; } -(无效)重置IDletimer; @结束 -
将.m文件更改为如下所示:
导入“TIMERUIApplication.h”
@应用程序的实现时间
//在这里,我们正在聆听任何触摸。如果屏幕接收到触摸,则定时器复位
-(void)sendEvent:(UIEvent*)事件
{
[超级发送事件:事件];
如果(!myidleTimer)
{
[自复位IDletimer];
}
NSSet*AllTouchs=[event AllTouchs];
如果([AllTouchs计数]>;0)
{
UITouchPhase=((UITouch*)[AllTouchAnyObject])阶段;
如果(相位==UITouchPhaseBegan | |相位==UITouchPhaseMoved)
{
[自复位IDletimer];
}
}
}
//如标签所示…重置计时器
-(无效)重置IDletimer
{
if(myidleTimer)
{
[myidleTimer失效];
}
//将等待时间转换为分钟而不是秒
int timeout=kApplicationTimeoutInMinutes*60;
myidleTimer=[NSTimer scheduledTimerWithTimeInterval:超时目标:自选择器:@selector(IdleTimerExcepended)userInfo:nil repeats:NO];
}
//如果计时器达到KapplicationTimeOutingMinutes中定义的限制,则发布此通知
-(无效)空闲时间
{
[[NSNotificationCenter defaultCenter]postNotificationName:kApplicationDidTimeoutNotification对象:nil];
}
@结束
-
进入您的Supporting Files文件夹并将main.m改为(不同于以前版本的XCode):
#导入<;UIKit/UIKit.h>; #导入“AppDelegate.h” #导入“TIMERUIApplication.h” int main(int argc,char*argv[]) { @自动释放池{ 返回UIApplicationMain(argc、argv、NSStringFromClass([TIMERUIApplication class])、NSStringFromClass([AppDelegate class]); } } -
在AppDelegate.m文件中编写剩余的代码。我遗漏了与此过程无关的代码。在.h文件中没有要进行的更改
导入“AppDelegate.h”
#导入“TIMERUIApplication.h”
@实现AppDelegate
@合成窗口=_窗口;
-(BOOL)应用程序:(UIApplication*)应用程序使用选项完成启动:(NSDictionary*)启动选项
{
[[NSNotificationCenter defaultCenter]addObserver:自选择器:@selector(ApplicationIDTimeout:)名称:kApplicationDidTimeoutNotification对象:nil];
返回YES;
}
-(无效)ApplicationIDTimeout:(NSNotification*)notif
{
NSLog(@“超过时间!!”);
//这就是storyboard vs xib文件的作用。在storyboard上,无论您要恢复到哪个视图控制器,请确保为其提供了与以下代码匹配的标识符。在我的示例中为“mainView”。我的storyboard文件名为MainStoryboard.storyboard,因此请确保您的文件名与storyboard WithName属性匹配。
UIViewController*控制器=[[UIStoryboard Storyboard with name:@“MainStoryboard”bundle:NULL]实例化视图控制器WithiIdentifier:@“mainView”];
[(UINavigationController*)self.window.rootViewController pushViewController:controller-animated:YES];
}
注意:只要检测到触摸,计时器就会启动。这意味着,如果用户触摸主屏幕(在我的例子中是“mainView”),即使没有离开该视图,相同的视图也会在分配的时间后自动覆盖。对我的应用程序来说没什么大不了的,但对你的应用程序来说可能是。只有在识别到触摸后,计时器才会重置。如果您想在回到您想要的页面后立即重置计时器,请在…pushViewController:controller animated:YES]之后包含此代码
[(TIMERUIApplication*)[UIApplication sharedApplication]ResetIdleTime];
这将导致视图每x分钟推一次,如果它只是坐在那里,没有交互。计时器仍将在每次识别触摸时重置,因此仍将工作
如果您有改进建议,请发表意见,特别是在当前显示“mainView”时禁用计时器的方法。我似乎无法找出if语句来让它注册当前视图。但我对我现在的处境很满意。下面是我对if语句的初步尝试,以便您可以看到我使用它的目的
-(void)applicationIDTimeout:(NSNotification*)notif
{
NSLog(@“超过时间!!”);
UIViewController*控制器=[[UIStoryboard Storyboard with name:@“MainStoryboard”bundle:NULL]实例化视图控制器WithiIdentifier:@“mainView”];
//我尝试了几种if语句,但都没用。总是转到else。
如果([controller isViewLoaded]){
NSLog(@“已经存在!”);
}
否则{
NSLog(@“回家”);
[(UINavigationController*)self.window.rootViewController pushViewController:controller-animated:YES];
//[(TIMERUIApplication*)[UIApplication sharedApplication]resetIdleTimer];
}
}
我仍然是一个n00b,可能并没有以最好的方式做每件事。欢迎提出建议