Слушайте все события касания в приложении iOS
Можно ли каким-то образом слушать и улавливать все события касания, происходящие в приложении?
Приложение, которое я сейчас разрабатываю, будет использоваться в демонстрационных залах и информационных киосках, и поэтому я хотел бы вернуться в стартовую часть приложения, если никаких касаний не было получено за пару минут. Это своего рода заставка, если хотите. Я планирую реализовать это, используя таймер, работающий в фоновом режиме, который должен быть reset и перезапускается каждый раз, когда событие касания происходит где-то в приложении. Но как я могу слушать события касания? Любые идеи или предложения?
Ответы
Ответ 1
Это очень просто.
Вам нужен подкласс UIApplication
(позвоните ему MyApplication
).
Вы изменяете свой main.m
, чтобы использовать его:
return UIApplicationMain(argc, argv, @"MyApplication", @"MyApplicationDelegate");
И вы переопределите метод [MyApplication sendEvent:]
:
- (void)sendEvent:(UIEvent*)event {
//handle the event (you will probably just reset a timer)
[super sendEvent:event];
}
Ответ 2
Для этого можно использовать подкласс UIWindow
, переопределяя hitTest:
. Затем в XIB вашего главного окна есть объект, обычно называемый просто Window
. Нажмите это, затем справа на панели "Утилиты" перейдите в "Тождества" (Alt-Command-3). В текстовом поле Class введите имя своего подкласса 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
Ответ 3
Для этого вы можете использовать распознаватель жестов. Подкласс UITapGestureRecognizer
и импортировать <UIKit/UIGestureRecognizerSubclass.h>
. Это определяет touchesBegan:
, touchesMoved:
, touchesEnded:
и touchesCancelled:
. Поместите свой код обработки касания соответствующими методами.
Произведите активацию распознавателя жестов в application:didFinishLaunchingWithOptions:
и добавьте его в UIWindow
. Установите cancelsTouchesInView
в NO
, и он пройдет все касания прозрачным образом.
Кредит: этот пост.
Ответ 4
Создайте класс "VApplication", который простирается от UIApplication
и вставьте этот код в соответствующий класс
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.m
#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
{
}
Ответ 5
Вы можете поместить прозрачный вид в верхней части иерархии представлений и выбрать в этом представлении, обрабатывать ли события касания, которые он получает, или передавать их для более низких просмотров.