2017-04-02 1 views
0

J'ai une fonction sliderValueChange qui met à jour un texte de UILabel. Je souhaite qu'il y ait une limite de temps pour effacer le texte de l'étiquette, mais je veux également que cette action "temporisée" soit annulée & redémarré ou retardée chaque fois que le UISlider est déplacé dans le délai avant que l'action "temporisé" ne prenne endroit.Comment annuler et redémarrer un événement minuté dans Swift?

Jusqu'à présent, c'est ce que j'ai:

let task = DispatchWorkItem { 
    consoleLabel.text = "" 
} 
func volumeSliderValueChange(sender: UISlider) { 

    task.cancel() 

    let senderValue = String(format: "%.2f", sender.value) 
    consoleLabel.text = "Volume: \(senderValue)" 

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3, execute: task) 
} 

De toute évidence, cette approche ne fonctionne pas, car cancel() apparemment ne peut pas être inversée .. (ou du moins je ne sais pas comment). Je ne sais pas non plus comment démarrer une nouvelle tâche à la fin de cette fonction qui sera annulée si la fonction est rappelée.

Est-ce que je vais dans ce sens? Y a-t-il quelque chose que je néglige pour faire ce travail?

+0

Je voudrais un NSTimer. Vous devez toujours annuler (invalider) et reporter la minuterie si vous voulez changer la période de la minuterie. Mais si vous voulez utiliser une tâche, oui, vous devrez créer et soumettre une nouvelle tâche. – Paulw11

Répondre

1

Utilisez une minuterie:

weak var clearTimer: Timer? 

Et:

override func viewDidLoad() { 
    super.viewDidLoad() 
    startClearTimer() 
} 

func startClearTimer() { 
    clearTimer = Timer.scheduledTimer(
    timeInterval: 3.0, 
    target: self, 
    selector: #selector(clearLabel(_:)), 
    userInfo: nil, 
    repeats: false) 
} 

func clearLabel(_ timer: Timer) { 
    label.text = "" 
} 

func volumeSliderValueChange(sender: UISlider) { 
    clearTimer?.invalidate() //Kill the timer 
    //do whatever you need to do with the slider value 
    startClearTimer() //Start a new timer 
} 
+0

Merci pour l'exemple clair! – PlateReverb

+0

@PlateReverb, comme dans cette réponse, la déclaration est 'func clearLabel (_ timer: Timer)', elle rend '#selector (clearLabel (_ :))' parfaitement valide. Votre [modification suggérée] (https://stackoverflow.com/review/suggested-edits/15732441) d'autre part est erronée et introduirait l'erreur suivante: 'error: utilisation de l'identificateur non résolu 'clearLabel (timer :)' selector: #selector (clearLabel (timer :)) ' –

+0

@ Cœur Ceci est étrange ... parce qu'avec' #selector (clearLabel (_ :)) 'j'obtiens l'erreur' Utilisation de l'identificateur non résolu 'clearLabel'' et en changeant ' _' à 'timer' le répare. J'ai déjà rencontré un problème similaire, et j'ai trouvé la solution sur un SO Q & A au même genre de problème. Je voudrais savoir pourquoi cette erreur s'est produite et pourquoi cette solution fonctionne pour moi, et pas vous ...? – PlateReverb

1

Le problème est que vous annulez la mauvaise chose. Vous ne voulez pas annuler la tâche. vous voulez annuler le compte à rebours que vous avez eu lorsque vous avez dit asyncAfter. Donc, utilisez un DispatchTimer ou un NSTimer (maintenant appelé un temporisateur dans Swift). Ce sont des compteurs qui peuvent être annulés. Et puis vous pouvez recommencer à compter.