Определить, касался ли пользователь экрана - PullRequest
0 голосов
/ 12 февраля 2012

Как определить, касался ли пользователь экрана за последние 5 секунд. Если нет, я бы хотел вызвать мой метод, чтобы скрыть панели навигации. Я нашел несколько ответов, но не смог их выяснить.

Спасибо

.hhhh

   #import <UIKit/UIKit.h>
    #import "PageView.h"
    #import "SlideShowViewController.h"
    #import "PagesCollectionViewController.h"

    @interface PageFlipperAppDelegate : NSObject <UIApplicationDelegate> {}

    @property (nonatomic, retain) IBOutlet UIWindow *window;

    @property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
    @property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
    @property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

    - (void)saveContext;
    - (NSURL *)applicationDocumentsDirectory;

    @end




    @protocol MyKindOfWindowDelegate;

    @interface MyKindOfWindow : UIWindow
    {

        NSTimer *tenthTimer;
        NSInteger tenthPast;
    }

    @property (nonatomic, assign) id <MyKindOfWindowDelegate> touchDelegate;

    -(void)startTimer;
    -(void)stopTimer;
    -(void)timerTick;

    @end

    @protocol MyKindOfWindowDelegate <NSObject>

    @required
    - (void) noTouchForFiveSeconds;
    @end

.mmmm

    #import "PageFlipperAppDelegate.h"

    @implementation PageFlipperAppDelegate

    @synthesize window;
    @synthesize managedObjectContext, managedObjectModel, persistentStoreCoordinator;
    - (void) noTouchForFiveSeconds  //!! your AppDelegate should implement this method
    {

        NSLog (@"No touch detected for over 5 seconds");

        //do your stuff

        //you can re-start timer immediately or somewhere later in the code
        [(MyKindOfWindow *)self.window startTimer];
    }


    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];

        [NSThread sleepForTimeInterval:2.75];



        self.window = [[MyKindOfWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
     [(MyKindOfWindow *)self.window setTouchDelegate:self];

        //PagesTableViewController *pagesTableViewController = [[PagesTableViewController alloc] initWithManagedObjectContext:[self managedObjectContext]];
        //[(UINavigationController *)[[self window] rootViewController] pushViewController:pagesTableViewController animated:NO];

        PagesCollectionViewController *collectionViewController = [[PagesCollectionViewController alloc] initWithManagedObjectContext:[self managedObjectContext]];
        //self.window = (UIWindow*)[[SlideShowViewController alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // [s setTouchDelegate:self];
        [(UINavigationController *)[[self window] rootViewController] pushViewController:collectionViewController animated:NO];

        [(UINavigationController *)[[self window] rootViewController] setToolbarHidden:NO animated:NO];
        //[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];

        //[pagesTableViewController release];
        [collectionViewController release];
        [[self window] makeKeyAndVisible];


        return YES;
    }

    - (void)applicationWillResignActive:(UIApplication *)application
    {
        //stopping timer since we're going to background
        [(MyKindOfWindow *)self.window stopTimer];
    }

    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        //you can start timer when app became active or somewhere later in the code
        [(MyKindOfWindow *)self.window startTimer];
    }


    - (void)applicationDidEnterBackground:(UIApplication *)application { [self saveContext]; }

    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        /*
         Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
         */
    }


    - (void)applicationWillTerminate:(UIApplication *)application { [self saveContext];
    }

    - (void)dealloc
    {
        [window release];
        [managedObjectContext release];
        [managedObjectModel release];
        [persistentStoreCoordinator release];
        [super dealloc];
    }

    - (void)awakeFromNib
    {
        /*
         Typically you should set up the Core Data stack here, usually by passing the managed object context to the first view controller.
         self..managedObjectContext = self.managedObjectContext;
         */
    }

    - (void)saveContext
    {
        NSError *error = nil;
        if ([self managedObjectContext])
        {
            if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
            {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
                 */
                //      NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            } 
        }
    }

    #pragma mark - Core Data stack

    /**
     Returns the managed object context for the application.
     If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
     */
    - (NSManagedObjectContext *)managedObjectContext
    {
        if (!managedObjectContext)
        {
            NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
            if (coordinator)
            {
                managedObjectContext = [[NSManagedObjectContext alloc] init];
                [managedObjectContext setPersistentStoreCoordinator:coordinator];
                [managedObjectContext setUndoManager:[[[NSUndoManager alloc] init] autorelease]];
            }
        }
        return managedObjectContext;
    }

    /**
     Returns the managed object model for the application.
     If the model doesn't already exist, it is created from the application's model.
     */
    - (NSManagedObjectModel *)managedObjectModel
    {
        if (!managedObjectModel)
        {
            NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"PageFlipper" withExtension:@"momd"];
            managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
        }    
        return managedObjectModel;
    }

    /**
     Returns the persistent store coordinator for the application.
     If the coordinator doesn't already exist, it is created and the application's store added to it.
     */
    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
    {
        if (persistentStoreCoordinator) return persistentStoreCoordinator;

        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"PageFlipper.sqlite"];

        NSError *error = nil;
        persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
        if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
        {
            /*
             Replace this implementation with code to handle the error appropriately.

             abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.

             Typical reasons for an error here include:
             * The persistent store is not accessible;
             * The schema for the persistent store is incompatible with current managed object model.
             Check the error message to determine what the actual problem was.


             If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.

             If you encounter schema incompatibility errors during development, you can reduce their frequency by:
             * Simply deleting the existing store:
             [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

             * Performing automatic lightweight migration by passing the following dictionary as the options parameter: 
             [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

             Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

             */
            //  NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }    

        return persistentStoreCoordinator;
    }

    #pragma mark - Application's Documents directory

    /**
     Returns the URL to the application's Documents directory.
     */
    - (NSURL *)applicationDocumentsDirectory
    {
        return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    }

    /*- (IBAction)toggleSettingsView:(id)sender
     {
     UIView *from = ([[settingsViewController view] isHidden] ? [padViewController view] : [settingsViewController view]);
     UIView *to = ([[settingsViewController view] isHidden] ? [settingsViewController view] : [padViewController view]);

     const NSTimeInterval flipDuration = 1.0;

     [UIView transitionWithView:from duration:flipDuration options:UIViewAnimationOptionTransitionFlipFromLeft animations:^(void)
     {
     [from setHidden:YES];
     [to setHidden:NO];
     } 
     completion:^(BOOL finished) {}
     ];
     [UIView transitionWithView:to duration:flipDuration options:UIViewAnimationOptionTransitionFlipFromLeft animations:^(void)
     {
     [from setHidden:YES];
     [to setHidden:NO];
     } 
     completion:^(BOOL finished) {}
     ];
     }*/

    @end


    @implementation MyKindOfWindow

    @synthesize touchDelegate = _touchDelegate;

    - (id)initWithFrame:(CGRect)aRect
    {
        if ((self = [super initWithFrame:aRect])) {

            _touchDelegate = nil;

            tenthPast = 0;
            tenthTimer = nil;
        }
        return self;
    }

    -(void)startTimer
    {

        NSLog (@"starting timer");
        tenthPast = 0;

        if (tenthTimer) [self stopTimer];

        tenthTimer  = [NSTimer timerWithTimeInterval:0.1
                                              target:self
                                            selector:@selector(timerTick)
                                            userInfo:nil    
                                             repeats:YES];

        [[NSRunLoop currentRunLoop] addTimer:tenthTimer forMode:NSDefaultRunLoopMode];
    }

    -(void)stopTimer
    {
        NSLog (@"stopping timer");
        [tenthTimer invalidate];
        tenthTimer = nil;
    }

    -(void)timerTick
    {
        //NSLog (@"1/10th of second passed");

        if (++tenthPast > 50) {

            if ((_touchDelegate != nil) && ([_touchDelegate respondsToSelector:@selector(noTouchForFiveSeconds)])) {

                NSLog (@"sending info to delegate");

                [self stopTimer];
                [_touchDelegate noTouchForFiveSeconds];            
            }
        }
    }

    - (void)sendEvent:(UIEvent *)event
    {

        [super sendEvent: event];

        if (event.type == UIEventTypeTouches) {

            //NSLog (@"touches detected - resetting counter");
            tenthPast = 0;
        }
    }

    @end

enter image description here

Ответы [ 3 ]

5 голосов
/ 12 февраля 2012

Создать таймер, который срабатывает за 5 секунд.Каждый раз, когда пользователь взаимодействует с пользовательским интерфейсом, аннулирует таймер и сбрасывает его.Если таймер срабатывает, вы знаете, что пользователь не взаимодействовал в течение последних 5 секунд.

3 голосов
/ 12 февраля 2012

В качестве дополнения к ответу jaminguy вы, вероятно, могли бы подкласс UIWindow переопределить - (void)sendEvent:(UIEvent *)event на:

- (void)sendEvent:(UIEvent *)event {

    [super sendEvent: event];

    if (event.type == UIEventTypeTouches) {


    //here you can invalidate & restart your 5s timer   
    }
}

Затем вы должны использовать этот подкласс в качестве основного окна для приложения (того, которое установлено в качестве ключа вappDelegate).

Некоторая литература:

Ссылка на класс UIWindow

Ссылка на класс UIEvent

Для достижениядля этого вам нужно добавить еще один класс в ваш проект (MyKindOfWindow).

файл MyKindOfWindow.h

#import <UIKit/UIKit.h>

@interface MyKindOfWindow : UIWindow

@end

файл MyKindOfWindow.m

#import "MyKindOfWindow.h"

@implementation MyKindOfWindow

- (void)sendEvent:(UIEvent *)event {

    [super sendEvent: event];

    if (event.type == UIEventTypeTouches) {

        NSLog (@"touch detected");

        //here you can invalidate & restart your 5s timer   
    }
}

@end

Вам также придется изменить AppDelegate.m .в начале вы добавляете

#import "MyKindOfWindow.h"

in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions и заменяете строку

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

на строку

self.window = [[MyKindOfWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

Теперь вы находитесь на половинепуть.В консоли отладки вы должны видеть «обнаружение касания» всякий раз, когда вы касаетесь экрана.Вы должны решить, куда вы поместите свой таймер (ответ jaminguy) в: MyKindOfWindow, AppDelegate, отдельный класс ...

1 голос
/ 15 февраля 2012

Я принял ваш код, чтобы он работал.

Основные изменения: pagesTableViewController и collectionViewController должны быть сохраненные свойства вашего приложения делегата.

self.window.rootViewController теперь определено в didFinishLaunchingWithOptions:, оба viewController-а выпущены в dealloc.

Обратите внимание, что вам действительно следует рассмотреть возможность размещения определений классов в отдельных файлах и возможно, начните использовать ARC для новых проектов.

PageFlipperAppDelegate.h

    #import <UIKit/UIKit.h>
    #import "PageView.h"
    #import "SlideShowViewController.h"
    #import "PagesCollectionViewController.h"

    @protocol MyKindOfWindowDelegate;

    @interface PageFlipperAppDelegate : NSObject <UIApplicationDelegate,MyKindOfWindowDelegate> {}

    @property (nonatomic, retain) IBOutlet UIWindow *window;
    @property (nonatomic, retain) PagesTableViewController* pagesTableViewController;
    @property (nonatomic, retain) SlideShowViewController* collectionViewController;

    @property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
    @property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
    @property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

    - (void)saveContext;
    - (NSURL *)applicationDocumentsDirectory;

    @end

    @interface MyKindOfWindow : UIWindow
    {

        NSTimer *tenthTimer;
        NSInteger tenthPast;
    }

    @property (nonatomic, retain) id <MyKindOfWindowDelegate> touchDelegate;

    -(void)startTimer;
    -(void)stopTimer;
    -(void)timerTick;

    @end

    @protocol MyKindOfWindowDelegate <NSObject>

    @required
    - (void) noTouchForFiveSeconds;
    @end

PageFlipperAppDelegate.m

 #import "PageFlipperAppDelegate.h"

    @implementation PageFlipperAppDelegate

    @synthesize window,pagesTableViewController,collectionViewController;
    @synthesize managedObjectContext, managedObjectModel, persistentStoreCoordinator;
    - (void) noTouchForFiveSeconds  //!! your AppDelegate should implement this method
    {

        NSLog (@"No touch detected for over 5 seconds");

        //do your stuff

        //you can re-start timer immediately or somewhere later in the code
        [(MyKindOfWindow *)self.window startTimer];
    }


    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];

        [NSThread sleepForTimeInterval:2.75]; 

        self.window = [[MyKindOfWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        [(MyKindOfWindow *)self.window setTouchDelegate:self];

        self.pagesTableViewController = [[PagesTableViewController alloc] initWithManagedObjectContext:[self managedObjectContext]];
        self.collectionViewController = [[PagesCollectionViewController alloc] initWithManagedObjectContext:[self managedObjectContext]];        

        self.window.rootViewController = self.pagesTableViewController;

        [self.pagesTableViewController pushViewController:pagesTableViewController animated:NO];        

        [self.pagesTableViewController setToolbarHidden:NO animated:NO];

        [[self window] makeKeyAndVisible];

        return YES;
    }

    - (void)dealloc
    {
        [pagesTableViewController release];
        [collectionViewController release];
        [window release];
        [managedObjectContext release];
        [managedObjectModel release];
        [persistentStoreCoordinator release];
        [super dealloc];
    }

Я сделал изменения в текстовом редакторе, поэтому возможны некоторые опечатки. Надеюсь, что нет.

EDIT:

Если вы хотите, чтобы определенный viewController запускал / останавливал таймер при его появлении / исчезновении, вы должны удалить все точности startTimer в appDelegate и поместить следующие строки в этот файл viewControllers .m:

#import "PageFlipperAppDelegate.h"

- (void)viewDidAppear:(BOOL)animated {

  [super viewDidAppear: animated];

  PageFlipperAppDelegate *appDelegate = (PageFlipperAppDelegate *)[[UIApplication sharedApplication] delegate];
  [(MyKindOfWindow *)appDelegate.window startTimer];
}

- (void)viewDidDisappear:(BOOL)animated {

  [super viewDidDisappear: animated];

  PageFlipperAppDelegate *appDelegate = (PageFlipperAppDelegate *)[[UIApplication sharedApplication] delegate];
  [(MyKindOfWindow *)appDelegate.window stopTimer];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...