Quelqu'un a-t-il implémenté une fonctionnalité où si l'utilisateur n'a pas touché l'écran pendant une certaine période, vous prenez une certaine action? J'essaie de trouver la meilleure façon de le faire.
Il y a cette méthode quelque peu liée dans UIApplication:
[UIApplication sharedApplication].idleTimerDisabled;
Ce serait bien si vous aviez quelque chose comme ça à la place:
NSTimeInterval timeElapsed = [UIApplication sharedApplication].idleTimeElapsed;
Ensuite, je pourrais configurer une minuterie et vérifier périodiquement cette valeur, et prendre des mesures lorsqu'elle dépasse un seuil.
J'espère que cela explique ce que je recherche. Quelqu'un a-t-il déjà abordé ce problème ou a-t-il des idées sur la façon dont vous le feriez? Merci.
ios
objective-c
iphone
idle-timer
Mike McMaster
la source
la source
Réponses:
Voici la réponse que je cherchais:
Demandez à votre délégué d'application de sous-classe UIApplication. Dans le fichier d'implémentation, remplacez la méthode sendEvent: comme suit:
où maxIdleTime et idleTimer sont des variables d'instance.
Pour que cela fonctionne, vous devez également modifier votre main.m pour indiquer à UIApplicationMain d'utiliser votre classe de délégué (dans cet exemple, AppDelegate) comme classe principale:
la source
NSTimer
instances s'il y a beaucoup de touches.J'ai une variante de la solution de minuterie d'inactivité qui ne nécessite pas de sous-classement UIApplication. Il fonctionne sur une sous-classe UIViewController spécifique, il est donc utile si vous n'avez qu'un seul contrôleur de vue (comme une application ou un jeu interactif peut avoir) ou si vous souhaitez uniquement gérer le délai d'inactivité dans un contrôleur de vue spécifique.
Il ne recrée pas non plus l'objet NSTimer chaque fois que le minuteur d'inactivité est réinitialisé. Il n'en crée un nouveau que si la minuterie se déclenche.
Votre code peut appeler
resetIdleTimer
pour tout autre événement qui peut nécessiter d'invalider la minuterie d'inactivité (comme une entrée d'accéléromètre importante).(code de nettoyage de la mémoire exclu par souci de concision.)
la source
Pour swift v 3.1
n'oubliez pas de commenter cette ligne dans AppDelegate // @ UIApplicationMain
Observer la notification dans une autre classe
la source
if idleTimer != nil
ensendEvent()
méthode?timeoutInSeconds
de la réponse du service Web?Ce fil a été d'une grande aide, et je l'ai encapsulé dans une sous-classe UIWindow qui envoie des notifications. J'ai choisi les notifications pour en faire un véritable couplage lâche, mais vous pouvez ajouter un délégué assez facilement.
Voici l'essentiel:
http://gist.github.com/365998
En outre, la raison du problème de sous-classe UIApplication est que le NIB est configuré pour créer ensuite 2 objets UIApplication car il contient l'application et le délégué. La sous-classe UIWindow fonctionne très bien cependant.
la source
En fait, l'idée de sous-classification fonctionne très bien. Ne faites pas de votre délégué la
UIApplication
sous - classe. Créez un autre fichier qui hérite deUIApplication
(par exemple myApp). Dans IB, définissez la classe de l'fileOwner
objet surmyApp
et dans myApp.m implémentez lasendEvent
méthode comme ci-dessus. Dans main.m faire:et voilà!
la source
Je viens de rencontrer ce problème avec un jeu qui est contrôlé par des mouvements, c'est-à-dire que le verrouillage de l'écran est désactivé mais devrait le réactiver en mode menu. Au lieu d'un minuteur, j'ai encapsulé tous les appels
setIdleTimerDisabled
dans une petite classe fournissant les méthodes suivantes:disableIdleTimer
désactive la minuterie d'inactivité,enableIdleTimerDelayed
lorsque vous entrez dans le menu ou tout ce qui devrait fonctionner avec la minuterie d'inactivité active etenableIdleTimer
est appelée à partir de laapplicationWillResignActive
méthode de votre AppDelegate pour garantir que toutes vos modifications sont correctement réinitialisées au comportement par défaut du système.J'ai écrit un article et fourni le code de la classe singleton IdleTimerManager Idle Timer Handling in iPhone Games
la source
Voici une autre façon de détecter l'activité:
Le minuteur est ajouté
UITrackingRunLoopMode
, de sorte qu'il ne peut se déclencher qu'en cas d'UITracking
activité. Il a également l'avantage de ne pas vous envoyer de spam pour tous les événements tactiles, vous informant ainsi s'il y a eu une activité dans les dernièresACTIVITY_DETECT_TIMER_RESOLUTION
secondes. J'ai nommé le sélecteurkeepAlive
car il semble être un cas d'utilisation approprié pour cela. Vous pouvez bien sûr faire ce que vous désirez avec l'information selon laquelle il y a eu une activité récemment.la source
En fin de compte, vous devez définir ce que vous considérez comme inactif: l'inactivité est-elle le résultat du fait que l'utilisateur ne touche pas l'écran ou est-ce l'état du système si aucune ressource informatique n'est utilisée? Il est possible, dans de nombreuses applications, que l'utilisateur fasse quelque chose même s'il n'interagit pas activement avec l'appareil via l'écran tactile. Bien que l'utilisateur soit probablement familier avec le concept de mise en veille de l'appareil et la notification que cela se produira via la gradation de l'écran, il n'est pas nécessairement le cas qu'il s'attend à ce que quelque chose se passe s'il est inactif - vous devez être prudent sur ce que vous feriez. Mais revenons à la déclaration originale - si vous considérez que le premier cas est votre définition, il n'y a pas de moyen vraiment facile de le faire. Vous auriez besoin de recevoir chaque événement tactile, le transmettre sur la chaîne de répondeurs au besoin tout en notant l'heure à laquelle il a été reçu. Cela vous donnera une base pour faire le calcul inactif. Si vous considérez que le deuxième cas est votre définition, vous pouvez jouer avec une notification NSPostWhenIdle pour essayer d'exécuter votre logique à ce moment-là.
la source
Il existe un moyen de faire cette application à l'échelle sans que les contrôleurs individuels aient à faire quoi que ce soit. Ajoutez simplement un outil de reconnaissance de gestes qui n'annule pas les touches. De cette façon, toutes les touches seront suivies pour le chronomètre, et les autres touches et gestes ne seront pas du tout affectés, donc personne d'autre n'a à le savoir.
Dans la méthode de lancement de la fin de votre délégué d'application, appelez simplement addGesture et vous êtes prêt. Toutes les touches passeront par les méthodes de CatchAllGesture sans que cela empêche la fonctionnalité des autres.
la source
-sendEvent:
est excessif etUITrackingRunLoopMode
ne gère pas de nombreux cas.