2011-12-09 4 views
18

アプリで発生しているすべてのタッチイベントを何とか聞いてキャッチすることは可能ですか?iOSアプリですべてのタッチイベントを聴く

私が現在開発中のアプリケーションは、ショールームや情報キオスクで使用されるため、数分間何も触れていない場合は、アプリの開始セクションに戻したいと思います。あなたが望むなら、ある種のスクリーンセーバー機能。バックグラウンドでタイマーを実行することでこれを実装する予定です。バックグラウンドでタイマーを設定すると、タッチイベントがアプリのどこかで発生するたびにリセットして再起動する必要があります。しかし、どのようにタッチイベントを聞くことができますか?任意のアイデアや提案?

答えて

31

本当に簡単です。

UIApplicationのサブクラスが必要です(MyApplicationとしましょう)。あなたは、ビュー階層の最上位に透視図を入れて、中に選択でき

 

- (void)sendEvent:(UIEvent*)event { 
    //handle the event (you will probably just reset a timer) 

    [super sendEvent:event]; 
} 
 
+0

のようなイベントが発生し、処理しますが発生。その他の回避策? – Legoless

+0

どのようにそれがあったかを理解する方法? –

+0

@AsadullahAli 'UIEvent'のドキュメント(https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIEvent_Class/index.html)を参照してください。すべてのイベントには、タイプ、サブタイプ、および検査可能な一連のタッチがあります。 – Sulthan

1

あなたはそれを使用するようにmain.mを変更します。

 

return UIApplicationMain(argc, argv, @"MyApplication", @"MyApplicationDelegate"); 
 

をそして、あなたはメソッド[MyApplication sendEvent:]をオーバーライドします受信したタッチイベントを処理するか、下位ビューに渡すかを表示します。

+0

これは、1つのビューしか表示されないアプリでのみ機能します。たとえば、別のView Controllerを表示するとすぐに破損します。 – DarkDust

+0

ビューを正しく設計していない場合。 –

+1

さて、 'presentModalViewController:animated:'はあなたの視界を遮るでしょうか、何か不足していますか?透明ビューをすべてのビューコントローラに挿入することをお勧めしますか?それは間違いなくその上に眺めを置かないように常にしなければならないので、確かに多くの作業と壊れやすいでしょう。または、これを確実にする簡単な方法はありますか? – DarkDust

3

サブクラスUIWindowは、hitTest:をオーバーライドすることでこれを行うことができます。メインウィンドウのXIBには、通常は単にWindowと呼ばれるオブジェクトがあります。それをクリックし、次にユーティリティパネルの右側でID(Alt-Command-3)に移動します。 クラステキストフィールドに、UIWindowサブクラスの名前を入力します。

MyWindow.h

@interface MyWindow : UIWindow 
@end 

MyWindow.m

@implementation MyWindow 

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    UIView *res; 

    res = [super hitTest:point withEvent:event]; 

    // Setup/reset your timer or whatever your want to do. 
    // This method will be called for every touch down, 
    // but not for subsequent events like swiping/dragging. 
    // Still, might be good enough if you want to measure 
    // in minutes. 

    return res; 
} 

@end 
+0

ここで問題となるのは、タッチが終了しても情報が得られないということです。 – Legoless

2

あなたは、このためにタップジェスチャー認識を使用することができます。サブクラスUITapGestureRecognizerとインポート<UIKit/UIGestureRecognizerSubclass.h>。これは、touchesBegan:,touchesMoved:,touchesEnded:およびtouchesCancelled:を定義します。適切な方法であなたのタッチ操作コードを入れてください。

ジェスチャ認識器をapplication:didFinishLaunchingWithOptions:にインスタンス化し、UIWindowに追加します。 cancelsTouchesInViewNOに設定すると、すべてのタッチが透過的に通過します。

クレジット:this post

3

VApplication.h

#import <Foundation/Foundation.h> 

// # of minutes before application times out 
#define kApplicationTimeoutInMinutes 10 

// Notification that gets sent when the timeout occurs 
#define kApplicationDidTimeoutNotification @"ApplicationDidTimeout" 

/** 
* This is a subclass of UIApplication with the sendEvent: method 
* overridden in order to catch all touch events. 
*/ 

@interface VApplication : UIApplication 
{ 
    NSTimer *_idleTimer; 
} 

/** 
* Resets the idle timer to its initial state. This method gets called 
* every time there is a touch on the screen. It should also be called 
* when the user correctly enters their pin to access the application. 
*/ 
- (void)resetIdleTimer; 

@end 

VApplication対応するクラスに、これらのコードのUIApplication から延びるクラス "VApplication" を作成して貼り付け。メートル

#import "VApplication.h" 
#import "AppDelegate.h" 

@implementation VApplication 

- (void)sendEvent:(UIEvent *)event 
{ 
    [super sendEvent:event]; 
    // Fire up the timer upon first event 
    if(!_idleTimer) { 
     [self resetIdleTimer]; 
    } 

    // Check to see if there was a touch event 
    NSSet *allTouches  = [event allTouches]; 

    if ([allTouches count] > 0) 
     { 
     UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase; 
     if (phase == UITouchPhaseBegan) 
      { 
      [self resetIdleTimer];   
      } 
     } 
} 

- (void)resetIdleTimer 
{ 
    if (_idleTimer) 
     { 
     [_idleTimer invalidate]; 
     } 

    // Schedule a timer to fire in kApplicationTimeoutInMinutes * 60 


// int timeout = [AppDelegate getInstance].m_iInactivityTime; 
    int timeout = 3; 
    _idleTimer = [NSTimer scheduledTimerWithTimeInterval:timeout 
                target:self 
               selector:@selector(idleTimerExceeded) 
               userInfo:nil 
               repeats:NO]; 

} 

- (void)idleTimerExceeded 
{ 
    /* Post a notification so anyone who subscribes to it can be notified when 
    * the application times out */ 


    [[NSNotificationCenter defaultCenter] 
    postNotificationName:kApplicationDidTimeoutNotification object:nil]; 
} 


@end 

当社

にクラス名 "VApplication" を置き換えMain.m

この

int main(int argc, char * argv[]) 
{ 
    @autoreleasepool { 
     return UIApplicationMain(argc, argv, @"VApplication", NSStringFromClass([AppDelegate class])); 

    } 
} 

のようなファイルは、対応するための通知を登録しますビューコントローラ

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidTimeout:) name:kApplicationDidTimeoutNotification object:nil]; 

、タイムアウト一度通知は、こののダウンサイズは、我々は、実行時にこれを行うことができないということである。この

- (void) applicationDidTimeout:(NSNotification *) notif //inactivity lead to any progress 
{ 


} 
+0

ありがとう、私はUITapGestureRecognizerが私のためにすべてのタッチイベントをキャッチしていなかったので、これを使用する必要がありました。 – Pellet

関連する問題