Come posso ritardare una chiamata di metodo di 1 secondo?


164

Esiste un modo semplice per ritardare una chiamata di metodo di 1 secondo?

Ho un oggetto UIImageViewche reagisce a un evento touch. Quando viene rilevato il tocco, nell'app si verificano alcune animazioni. Dopo un secondo, voglio chiamare un altro metodo. In questo caso, non posso usare il animationDidStopselettore.


Esistono sicuramente diversi modi per farlo, uno di questi potrebbe essere semplicemente quello di utilizzare sleep () per sospendere il programma / thread per un numero di millisecondi, tuttavia penso che potresti voler dirci che cosa stai esattamente cercando di realizzare facendo questo? Voglio dire, qual è il tuo vero problema? L'idea di ritardare una chiamata di metodo sembra essere una 'soluzione', una che non sembra troppo bella per essere onesta. Quindi, raccontaci di più sullo scenario che hai in mente.
nessuno

Risposte:


254
performSelector:withObject:afterDelay:

Documento di riferimento


7
Questa è la risposta corretta Si prega di consultare developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/… :
danneggia

C'è un modo per qualcosa con il valore di ritorno del metodo che viene chiamato? O devo impostarlo per modificare il parametro se voglio ottenere alcune informazioni da esso?
Gordon Gustafson,

se qualcuno è interessato a come annullare una chiamata pianificata: [NSObject cancelPreviousPerformRequestsWithTarget: selettore yourTarget: oggetto aSelector: anArgument];
vir us

192

Puoi anche usare un blocco

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [object method]; 
});

Il più delle volte vorrai usare dispatch_get_main_queue, anche se se non ci fosse un'interfaccia utente nel metodo potresti usare una coda globale .

Modificare:

Versione Swift 3:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    object.method()
}

Allo stesso modo, DispatchQueue.global().asyncAfter(...potrebbe anche essere una buona opzione.


Ho trovato questa soluzione più semplice di performSelector quando si mischiano direttamente C e ObjC
Paul Slocum,

1
Sfortunatamente dispatch_get_current_queue è deprecato da iOS6
chrisben,

3
Aggiornato per utilizzare dispatch_get_main_queue invece di dispatch_get_current_queue
mcfedr

2
Xcode ora completerà automaticamente questo, basta iniziare a digitare dispatch_aftere premere
invio

1
Soprattutto ora Xcode lo completa automaticamente durante la digitazione dispatch_after, questo è davvero un modo super semplice per farlo, inoltre puoi passare le proprietà al metodo che stai chiamando, il che è fantastico.
Erik van der Neut,

128

Il modo migliore per fare è:

[self performSelector:@selector(YourFunctionName) 
           withObject:(can be Self or Object from other Classes) 
           afterDelay:(Time Of Delay)];

puoi anche passare zero come con il parametroObject.

esempio :

[self performSelector:@selector(subscribe) withObject:self afterDelay:3.0 ];

3
Perché dovresti passare da solo a te stesso?
Eric

2
E perché dovresti passare una variabile a un metodo che accetta zero argomenti?
ciaozimi

23

Ci sono già molte risposte e sono tutte corrette. Nel caso in cui desideri utilizzarlo dispatch_after, dovresti cercare lo snippet che è incluso nella parte Code Snippet Libraryin basso a destra (dove puoi selezionare gli UIelementi).

inserisci qui la descrizione dell'immagine

Quindi devi solo chiamare questo snippet scrivendo invio nel codice:

inserisci qui la descrizione dell'immagine


16

È possibile utilizzare il selettore di esecuzione per dopo che il metodo di ritardo di 0,1 secondi viene chiamato per il codice seguente per eseguire questa operazione.

[self performSelector:@selector(InsertView)  withObject:nil afterDelay:0.1]; 

9

Puoi anche:

[UIView animateWithDuration:1.0
                 animations:^{ self.view.alpha = 1.1; /* Some fake chages */ }
                 completion:^(BOOL finished)
{
    NSLog(@"A second lapsed.");
}];

In questo caso devi falsificare alcune modifiche in alcune viste per far funzionare l'animazione. È davvero confuso, ma adoro le cose basate sul blocco. O termina la risposta @mcfedr di seguito.


waitFor(1.0, ^
{
    NSLog(@"A second lapsed");
});

typedef void (^WaitCompletionBlock)();
void waitFor(NSTimeInterval duration, WaitCompletionBlock completion)
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC),
                   dispatch_get_main_queue(), ^
    { completion(); });
}

Non sono sicuro, ma penso che la prima opzione che suggerisci possa avere effetti collaterali di cui gli utenti dovrebbero essere a conoscenza, ad esempio bloccando l'interazione dell'utente su parti dell'interfaccia utente. Il mio istinto è che provocherebbe anche un inutile esaurimento della CPU o di altre risorse, ma non ho verificato.
Bjorn Roche,

8

Puoi farlo

[self performSelector:@selector(MethodToExecute) withObject:nil afterDelay:1.0 ];

4

Swift 2.x

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
 dispatch_after(delayTime, dispatch_get_main_queue()) {
 print("do some work")
}

Swift 3.x - & - Swift 4

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
    print("do some work")
}

o passare a escaping closure

func delay(seconds: Double, completion: @escaping()-> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + seconds, execute: completion)
}

1

Esiste una soluzione Swift 3 dalla soluzione selezionata:

self.perform(#selector(self.targetMethod), with: self, afterDelay: 1.0)

E c'è il metodo

@objc fileprivate func targetMethod(){

}

0

Utilizzare in Swift 3

perform(<Selector>, with: <object>, afterDelay: <Time in Seconds>)

-34

NOTA: questo metterà in pausa l'intero thread, non solo l'unico metodo.
Effettuare una chiamata in modalità sleep / wait / halt per 1000 ms prima di chiamare il metodo?

Sleep(1000); // does nothing the next 1000 mSek

Methodcall(params); // now do the real thing

Modifica: la risposta sopra si applica alla domanda generale "Come posso ritardare una chiamata di metodo di 1 secondo?", Che era la domanda posta al momento della risposta (infatti la risposta è stata data entro 7 minuti dalla domanda originale: - )). Non sono state fornite informazioni sulla lingua in quel momento, quindi smetti gentilmente di lamentarti del modo corretto di usare il sonno in XCode della mancanza di lezioni ...


Solo nel thread corrente, altri thread continueranno a essere eseguiti.
Marc Charbonneau,

4
Accidenti. Capisco perché questo è stato votato in negativo un paio di volte, ma chi diavolo l'ha visto a -27 e ha deciso che ne era necessario un altro? -3 o qualcosa del genere non capisce. Perché non modificare semplicemente la risposta per dire "questo metterà in pausa il tuo intero thread" o qualcosa invece di ridimensionarlo?
Albert Renshaw,

E se volessi solo mettere in pausa l'intero thread? Sembra un'opzione valida se viene fornito con un avviso decente.
Departamento B,

@AlbertRenshaw Sono totalmente d'accordo con te. Sono qui con i suoi 35 bassi e gli ho dato il mio. Vedo di più che attaccare così male gli utenti di bassa reputazione. Nessuno effettuerà alcuna modifica o specificherà nulla. Ho visto una risposta oggi che è davvero affogato. L'unico errore che ha fatto quella persona è che ha risposto con una rapida domanda con un linguaggio obiettivo c. Se si tratta di un errore enorme, voglio mostrare così tante risposte rapide sotto le domande dell'obiettivo c.
soorej babu
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.