2017-09-04 3 views
0

Je développe une application iOS en utilisant un appareil Bluetooth avec un bouton qui communique avec l'iPad. Fondamentalement, je veux une demande d'aide à émettre lorsque le bouton est maintenu pendant 3 secondes ou plus. De toute la documentation que j'ai trouvée, je n'ai pas trouvé de moyen d'arrêter un Timer sans l'invalider, avec la méthode invalidate(). De Apple's documentation:Comment redémarrer ou arrêter une minuterie dans Swift sans la détruire?

La boucle d'exécution supprime la temporisation (et la référence forte qu'elle avait à la minuterie), soit juste avant le retour de la méthode invalidate () ou à un moment plus tard. Une fois invalidés, les objets de minuteur ne peuvent pas être réutilisés.

L'idée dans mon code est que lorsque le bouton est enfoncé, le booléen buttonWasHeld est définie sur true et une minuterie est déclenchée. Si le bouton est relâché, buttonWasHeld est défini sur false et, lorsque le temporisateur appelle le gestionnaire, il sait que le bouton n'a pas été maintenu assez longtemps. Ensuite, si vous appuyez de nouveau sur le bouton dans les 3 secondes, la minuterie est à nouveau configurée.

Problème: chaque pression sur un bouton provoque une nouvelle temporisation, ce qui signifie qu'une pression répétée sur le bouton lance également la demande d'aide. De plus, toutes ces minuteries sont adressées par la même variable, donc je ne peux pas les différencier.

Existe-t-il un moyen de dire de façon unique quelle a été la dernière minuterie créée? Ou un moyen obscur de faire une pause/l'arrêter?

Voici le morceau de code contrôle cette fonction:

var buttonTimer: Timer? 
var buttonWasHeld: Bool = false 

func didUpdateModule() { 
    // gpioListener takes a handler to be called whenever a button is 
    // pressed or released. isPushed is a self-explanatory boolean. 
    self.controller.gpioListener() { isPushed in 
     if isPushed { 
      self.buttonWasHeld = true 
      self.buttonTimer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { _ in 
       if self.buttonWasHeld { 
        // Issue a help request 
        self.delegate?.notifyDevice(message: .HELP) 
        print("Asking for help") 
       } 
      } 
      print("Button was pressed") 
     } 
     else { 
      self.buttonWasHeld = false 
      // Also tried "self.buttonTimer = nil" here. Didn't work 
      print("Button was released") 
     } 
    } 
} 
+1

double possible de [Comment arrêter NSTimer] (https://stackoverflow.com/questions/3509012/how-to-stop-nstimer) – the4kman

+0

La solution était exactement ce que je cherche à éviter, invalidant le minuteur. Cela rendra cette minuterie inutilisable. –

+0

Chaque fois que vous voulez créer un nouveau minuteur, vérifiez si le minuteur stocké dans 'buttonTimer' a été invalidé en utilisant' isValid'. S'il a été invalidé, créez-en un nouveau, sinon utilisez celui en cours. – Sweeper

Répondre

0

Comme d'habitude, la réponse était assez simple.

Si la minuterie est déclarée comme faible var, et pas seulement var, seul le faible instanciation sera invalidée. Ainsi, le code doit être:

weak var buttonTimer: Timer? 
var buttonWasHeld: Bool = false 

func didUpdateModule() { 
    (...) 
     else { 
      // This will only invalidate the current running timer, 
      // not the whole variable :) 
      self.buttonTimer.invalidate 
      // I removed buttonWasHeld, it's not necessary anymore ;) 
      print("Button was released") 
     } 
    } 
}