2010-02-09 12 views
22

C'è un modo più semplice di aspettare per un determinato periodo di tempo a Cocoa di quello che ho messo a punto sotto?attesa per una durata specifica in Cocoa

- (void) buttonPressed { 
    [self makeSomeChanges]; 

    // give the user some visual feedback and wait a bit so he can see it 
    [self displayThoseChangesToTheUser]; 
    [self performSelector:@selector(buttonPressedPart2:) withObject:nil afterDelay:0.35]; 
} 

- (void) buttonPressedPart2: (id)unused { 
    [self automaticallyReturnToPreviousView]; 
} 

Giusto per essere chiari, non c'è funzionale problema con questo codice - la mia unica carne bovina è un stilistica uno. Nel mio caso il flusso è abbastanza semplice che funziona, ma cercare di incapsulare o gettare in alcuni condizionali e le cose potrebbero girare brutto. E 'stato sorta di fastidioso a me che non riuscivo a trovare un modo per aspettare e poi tornare a quello stesso punto nel codice come questo (fittizia) Esempio:

- (void) buttonPressed { 
    [self doStuff]; 
    [UIMagicUnicorn waitForDuration:0.35]; 
    [self doStuffAfterWaiting]; 
} 

risposta

61

C'è

usleep(1000000); 

e

[NSThread sleepForTimeInterval:1.0f]; 

entrambi i quali dormirà per 1 secondo.

+8

ed entrambi dei quali saranno bloccare il filo di fare qualsiasi altra cosa. male, se è nella U.I. filo. – pestilence669

+3

Vero. Se hai bisogno che l'interfaccia utente sia reattiva durante questo periodo, l'approccio suggerito nella domanda, un NSTimer che si attiva una volta (come suggerisci tu), o una discussione in background che esegue questo ritardo sarebbe meglio. –

+0

Grazie - questo è quello che mi stavo chiedendo, probabilmente ci saremmo imbattuti in esso se "dormire" fosse uno dei tanti sinonimi di "attesa" su cui avevo pensato di cercare. Grazie anche a Pestilenza per gli avvertimenti su quando * non * usarli. –

2

Probabilmente vuole utilizzare un NSTimer e lo hanno invia un messaggio "doStuffAfterWaiting" come callback. Qualsiasi tipo di "sonno" bloccherà il filo fino a quando non si risveglierà. Se è nel tuo U.I. thread, causerà la visualizzazione della tua app "dead". Anche se non è così, è una cattiva forma. L'approccio callback libera la CPU per svolgere altre attività fino a quando non viene raggiunto l'intervallo di tempo specificato.

Questo doc ha esempi di utilizzo e discute le differenze su come & dove creare il proprio timer.

Naturalmente, performSelector: afterDelay: fa la stessa cosa.

3

Non sono sicuro che esista (ancora), ma con blocchi in 10.6 (o PLBlocks in 10.5 e su iPhone) dovrebbe essere abbastanza facile scrivere un piccolo wrapper come performBlock:afterDelay: che fa esattamente quello che vuoi senza la necessità di dormire l'intero thread. Sarebbe davvero un piccolo pezzo di codice utile.

Mike Ash ha written about an approach like this on his blog:

NSString *something = ...; 
RunAfterDelay(0, ^{ 
    NSLog(@"%@", something); 
    [self doWorkWithSomething: something]; 
}); 
2

Cosa c'è di sbagliato con un semplice usleep? Voglio dire, tranne che per il bene di "Cacao purezza", è ancora molto più breve rispetto ad altre soluzioni :)

+2

Blocca la discussione. Se viene chiamato nel modo principale, stai effettivamente uccidendo il ciclo di esecuzione e l'app apparirà "morta" – pestilence669

+3

Quindi non chiamare dal principale – Charlie

10

Ecco il modo NSTimer di farlo. Potrebbe essere ancora più brutto del metodo che stai usando, ma permette di ripetere eventi, quindi lo preferisco.

[NSTimer scheduledTimerWithTimeInterval:0.5f 
           target:self 
           selector: @selector(doSomething:) 
           userInfo:nil 
           repeats:NO]; 

si vuole evitare qualcosa di simile usleep() che sarà solo appendere il vostro app e farlo sentire non risponde.

+1

Penso che tu intenda "NSTimer", non "NSThread". –

+7

"' Vuoi evitare qualcosa come noi addormentati() che appende semplicemente la tua app e la fa sentire insensibile. "Abbastanza sicuro è vero solo se hai chiamato' usleep' dal thread principale. – chown

0

Se non ti dispiace una soluzione asincrona, qui si va:

[[NSOperationQueue currentQueue] addOperationWithBlock:^{ 
    [self doStuffAfterWaiting]; 
}];