Alguém implementou um recurso em que, se o usuário não toca na tela por um determinado período, você executa uma determinada ação? Estou tentando descobrir a melhor maneira de fazer isso.
Existe este método um pouco relacionado no UIApplication:
[UIApplication sharedApplication].idleTimerDisabled;
Seria bom se você tivesse algo parecido com isto:
NSTimeInterval timeElapsed = [UIApplication sharedApplication].idleTimeElapsed;
Então eu poderia configurar um cronômetro e verificar periodicamente esse valor e executar alguma ação quando ele exceder um limite.
Espero que isso explique o que estou procurando. Alguém já resolveu esse problema ou já pensou em como o faria? Obrigado.
ios
objective-c
iphone
idle-timer
Mike McMaster
fonte
fonte
Respostas:
Aqui está a resposta que eu estava procurando:
Faça com que seu aplicativo delegue a subclasse UIApplication. No arquivo de implementação, substitua o método sendEvent: da seguinte maneira:
onde maxIdleTime e idleTimer são variáveis de instância.
Para que isso funcione, você também precisa modificar seu main.m para dizer ao UIApplicationMain para usar sua classe delegada (neste exemplo, AppDelegate) como a classe principal:
fonte
NSTimer
instâncias se houver muitos toques.Eu tenho uma variação da solução de timer ocioso que não requer a subclasse de UIApplication. Ele funciona em uma subclasse UIViewController específica, portanto, é útil se você tiver apenas um controlador de visualização (como um aplicativo ou jogo interativo) ou desejar apenas manipular o tempo limite inativo em um controlador de visualização específico.
Também não recria o objeto NSTimer toda vez que o timer ocioso é redefinido. Ele cria apenas um novo se o timer disparar.
Seu código pode solicitar
resetIdleTimer
outros eventos que possam precisar invalidar o timer inativo (como entrada significativa do acelerômetro).(código de limpeza de memória excluído por brevidade.)
fonte
Para swift v 3.1
não se esqueça de comentar esta linha no AppDelegate // @ UIApplicationMain
Observando a notificação em qualquer outra classe
fonte
if idleTimer != nil
insendEvent()
?timeoutInSeconds
da resposta do serviço da web?Esse tópico foi uma grande ajuda e eu o envolvi em uma subclasse UIWindow que envia notificações. Escolhi as notificações para torná-lo um acoplamento flexível, mas você pode adicionar um delegado com bastante facilidade.
Aqui está a essência:
http://gist.github.com/365998
Além disso, o motivo do problema da subclasse UIApplication é que o NIB está configurado para criar 2 objetos UIApplication, pois contém o aplicativo e o delegado. A subclasse UIWindow funciona muito bem.
fonte
Na verdade, a ideia de subclasse funciona muito bem. Apenas não faça do seu delegado a
UIApplication
subclasse. Crie outro arquivo que herda deUIApplication
(por exemplo, myApp). No IB, defina a classe dofileOwner
objeto comomyApp
e em myApp.m, implemente osendEvent
método como acima. Em main.m do:et voilà!
fonte
Acabei de encontrar este problema com um jogo controlado por movimentos, ou seja, com o bloqueio de tela desativado, mas deve ativá-lo novamente no modo de menu. Em vez de um timer, encapsulei todas as chamadas para
setIdleTimerDisabled
uma classe pequena, fornecendo os seguintes métodos:disableIdleTimer
desativa o timer ocioso,enableIdleTimerDelayed
ao entrar no menu ou o que quer que seja executado com o timer ocioso ativo eenableIdleTimer
é chamado peloapplicationWillResignActive
método do AppDelegate para garantir que todas as suas alterações sejam redefinidas corretamente para o comportamento padrão do sistema.Escrevi um artigo e forneci o código para a classe Singleton IdleTimerManager Idle Timer Handling in iPhone Games
fonte
Aqui está outra maneira de detectar atividade:
O temporizador é adicionado
UITrackingRunLoopMode
para poder disparar apenas se houverUITracking
atividade. Ele também tem a vantagem de não enviar spam para todos os eventos de toque, informando se houve atividade nos últimosACTIVITY_DETECT_TIMER_RESOLUTION
segundos. Eu nomeei o seletorkeepAlive
, pois parece um caso de uso apropriado para isso. Obviamente, você pode fazer o que quiser com a informação de que houve atividade recentemente.fonte
Por fim, você precisa definir o que considera inativo - é inativo o resultado do usuário não tocar na tela ou é o estado do sistema se nenhum recurso de computação estiver sendo usado? É possível, em muitos aplicativos, que o usuário esteja fazendo algo, mesmo que não esteja interagindo ativamente com o dispositivo através da tela de toque. Embora o usuário provavelmente esteja familiarizado com o conceito de dispositivo em suspensão e com o aviso de que isso ocorrerá através do escurecimento da tela, não é necessariamente o caso em que eles esperam que algo aconteça se estiverem ociosos - você precisa ter cuidado sobre o que você faria. Mas voltando à declaração original - se você considera o 1º caso a sua definição, não há realmente uma maneira fácil de fazer isso. Você precisaria receber cada evento de toque, transmitindo-o na cadeia de resposta conforme necessário, observando a hora em que foi recebido. Isso fornecerá algumas bases para fazer o cálculo inativo. Se você considerar o segundo caso como sua definição, poderá jogar com uma notificação NSPostWhenIdle para tentar executar sua lógica naquele momento.
fonte
Existe uma maneira de fazer esse aplicativo amplamente, sem que os controladores individuais precisem fazer nada. Basta adicionar um reconhecedor de gestos que não cancela toques. Dessa forma, todos os toques serão rastreados no cronômetro, e outros toques e gestos não serão afetados, de modo que ninguém mais precisará saber sobre isso.
No método de inicialização do delegado do aplicativo, basta ligar para addGesture e está tudo pronto. Todos os toques passarão pelos métodos do CatchAllGesture sem impedir a funcionalidade de outros.
fonte
-sendEvent:
é um exagero eUITrackingRunLoopMode
não lida com muitos casos.