iOS 在一段时间不活动后执行操作(无用户交互) [英] iOS perform action after period of inactivity (no user interaction)

查看:23
本文介绍了iOS 在一段时间不活动后执行操作(无用户交互)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何向基于用户交互(或缺乏交互)的 iOS 应用添加计时器?换句话说,如果 2 分钟没有用户交互,我想让应用程序做一些事情,在这种情况下导航到初始视图控制器.如果有人在 1:55 触摸屏幕,计时器将重置.我认为这需要是一个全局计时器,因此无论您在哪个视图上,缺乏交互都会启动计时器.虽然,我可以在每个视图上创建一个独特的计时器.有没有人对以前做过的任何建议、链接或示例代码?

How can I add a timer to my iOS app that is based on user interaction (or lack thereof)? In other words, if there is no user interaction for 2 minutes, I want to have the app do something, in this case navigate to the initial view controller. If at 1:55 someone touches the screen, the timer resets. I would think this would need to be a global timer so no matter which view you are on, the lack of interaction starts the timer. Although, I could create a unique timer on each view. Does anyone have any suggestions, links or sample code where this has been done before?

推荐答案

Anne 提供的链接是一个很好的起点,但是,作为 n00b 的我,很难将其转化为我现有的项目.我发现了一个博客 [原始博客不再存在] 提供了一个更好的一步一步,但它不是为 XCode 4.2 和使用故事板编写的.以下是我如何让不活动计时器为我的应用工作的文章:

The link that Anne provided was a great starting point, but, being the n00b that I am, it was difficult to translate into my existing project. I found a blog [original blog no longer exists] that gave a better step-by-step, but it wasn't written for XCode 4.2 and using storyboards. Here is a write up of how I got the inactivity timer to work for my app:

  1. 创建一个新文件 -> Objective-C 类 -> 输入名称(在我的例子中是 TIMERUIApplication)并将子类更改为 UIApplication.您可能必须在子类字段中手动键入此内容.您现在应该拥有相应的 .h 和 .m 文件.

  1. Create a new file -> Objective-C class -> type in a name (in my case TIMERUIApplication) and change the subclass to UIApplication. You may have to manually type this in the subclass field. You should now have the appropriate .h and .m files.

将.h文件改成如下:

#import <Foundation/Foundation.h>

//the length of time before your application "times out". This number actually represents seconds, so we'll have to multiple it by 60 in the .m file
#define kApplicationTimeoutInMinutes 5

//the notification your AppDelegate needs to watch for in order to know that it has indeed "timed out"
#define kApplicationDidTimeoutNotification @"AppTimeOut"

@interface TIMERUIApplication : UIApplication
{
    NSTimer     *myidleTimer;
}

-(void)resetIdleTimer;

@end

  • 将.m文件改为如下:

  • Change the .m file to read as follows:

    #import "TIMERUIApplication.h"
    
    @implementation TIMERUIApplication
    
    //here we are listening for any touch. If the screen receives touch, the timer is reset
    -(void)sendEvent:(UIEvent *)event
    {
        [super sendEvent:event];
    
        if (!myidleTimer)
        {
            [self resetIdleTimer];
        }
    
        NSSet *allTouches = [event allTouches];
        if ([allTouches count] > 0)
        {
            UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
            if (phase == UITouchPhaseBegan || phase == UITouchPhaseMoved)
            {
                [self resetIdleTimer];
            }
    
        }
    }
    //as labeled...reset the timer
    -(void)resetIdleTimer
    {
        if (myidleTimer)
        {
            [myidleTimer invalidate];
        }
        //convert the wait period into minutes rather than seconds
        int timeout = kApplicationTimeoutInMinutes * 60;
        myidleTimer = [NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:@selector(idleTimerExceeded) userInfo:nil repeats:NO];
    
    }
    //if the timer reaches the limit as defined in kApplicationTimeoutInMinutes, post this notification
    -(void)idleTimerExceeded
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:kApplicationDidTimeoutNotification object:nil];
    }
    
    
    @end
    

  • 进入您的 Supporting Files 文件夹并将 main.m 更改为此(与以前版本的 XCode 不同):

  • Go into your Supporting Files folder and alter main.m to this (different from prior versions of XCode):

    #import <UIKit/UIKit.h>
    
    #import "AppDelegate.h"
    #import "TIMERUIApplication.h"
    
    int main(int argc, char *argv[])
    {
        @autoreleasepool {
            return UIApplicationMain(argc, argv, NSStringFromClass([TIMERUIApplication class]), NSStringFromClass([AppDelegate class]));
        }
    }
    

  • 在您的 AppDelegate.m 文件中编写剩余的代码.我省略了与此过程无关的代码..h 文件中没有任何更改.

  • Write the remaining code in your AppDelegate.m file. I've left out code not pertaining to this process. There is no change to make in the .h file.

    #import "AppDelegate.h"
    #import "TIMERUIApplication.h"
    
    @implementation AppDelegate
    
    @synthesize window = _window;
    
    -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    {      
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidTimeout:) name:kApplicationDidTimeoutNotification object:nil];
    
        return YES;
    }
    
    -(void)applicationDidTimeout:(NSNotification *) notif
    {
        NSLog (@"time exceeded!!");
    
    //This is where storyboarding vs xib files comes in. Whichever view controller you want to revert back to, on your storyboard, make sure it is given the identifier that matches the following code. In my case, "mainView". My storyboard file is called MainStoryboard.storyboard, so make sure your file name matches the storyboardWithName property.
        UIViewController *controller = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:@"mainView"];
    
        [(UINavigationController *)self.window.rootViewController pushViewController:controller animated:YES];
    }
    

  • 注意:只要检测到触摸,计时器就会启动.这意味着如果用户触摸主屏幕(在我的例子中是mainView"),即使没有导航离开该视图,在分配的时间后,同一个视图也会自动推过自己.对我的应用程序来说没什么大不了的,但对你来说可能是.计时器只会在识别到触摸后重置.如果您想在返回到您想要访问的页面后立即重置计时器,请在 ...pushViewController:controller animation:YES];

    Notes: The timer will start anytime a touch is detected. This means that if the user touches the main screen (in my case "mainView") even without navigating away from that view, the same view will push over itself after the allotted time. Not a big deal for my app, but for yours it might be. The timer will only reset once a touch is recognized. If you want to reset the timer as soon as you get back to the page you want to be at, include this code after the ...pushViewController:controller animated:YES];

    [(TIMERUIApplication *)[UIApplication sharedApplication] resetIdleTimer];
    

    如果它只是坐在那里没有交互,这将导致视图每 x 分钟推送一次.每次识别到触摸时,计时器仍会重置,因此它仍然有效.

    This will cause the view to push every x minutes if it's just sitting there with no interaction. The timer will still reset every time it recognizes a touch, so that will still work.

    如果您有改进建议,请发表评论,特别是如果当前正在显示mainView",请以某种方式禁用计时器.我似乎无法弄清楚我的 if 语句来注册当前视图.但我对自己所处的位置感到满意.下面是我对 if 语句的初步尝试,因此您可以了解我的意图.

    Please comment if you have suggested improvements, especially someway to disable the timer if the "mainView" is currently being displayed. I can't seem to figure out my if statement to get it to register the current view. But I'm happy with where I'm at. Below is my initial attempt at the if statement so you can see where I was going with it.

    -(void)applicationDidTimeout:(NSNotification *) notif
    {
        NSLog (@"time exceeded!!");
        UIViewController *controller = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:@"mainView"];
    
        //I've tried a few varieties of the if statement to no avail. Always goes to else.
        if ([controller isViewLoaded]) {
            NSLog(@"Already there!");
        }
        else {
            NSLog(@"go home");
            [(UINavigationController *)self.window.rootViewController pushViewController:controller animated:YES];
            //[(TIMERUIApplication *)[UIApplication sharedApplication] resetIdleTimer];
        }
    }
    

    我仍然是一个 n00b,可能没有以最好的方式完成所有事情.建议总是受欢迎的.

    I am still a n00b and may have not done everything the best way. Suggestions are always welcome.

    这篇关于iOS 在一段时间不活动后执行操作(无用户交互)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆