Domanda

Per ripetere una chiamata di metodo (o un messaggio di invio, credo che il termine appropriato è) ogni x secondi, è meglio utilizzare un NSTimer (di NSTimer scheduledTimerWithTimeInterval: Obiettivo: selettore: UserInfo: ripete: ) o di avere il metodo ricorsivo stessa chiamata al termine (utilizzando performSelector: withObject: afterDelay)? Quest'ultimo non fa uso di un oggetto, ma forse la sua meno chiaro / leggibile? Inoltre, solo per darvi un'idea di quello che sto facendo, il suo solo una vista con un'etichetta che conta fino a 12:00 a mezzanotte, e quando si arriva a 0, lampeggerà il tempo (0:00:00) e riprodurre un segnale acustico per sempre.

Grazie.

Edit: anche, quale sarebbe il modo migliore per giocare più volte uno SystemSoundID (per sempre)? Edit: ho finito per usare questo per riprodurre lo SystemSoundID per sempre:

// Utilities.h
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioServices.h>


static void soundCompleted(SystemSoundID soundID, void *myself);

@interface Utilities : NSObject {

}

+ (SystemSoundID)createSystemSoundIDFromFile:(NSString *)fileName ofType:(NSString *)type;
+ (void)playAndRepeatSystemSoundID:(SystemSoundID)soundID;
+ (void)stopPlayingAndDisposeSystemSoundID;

@end


// Utilities.m
#import "Utilities.h"


static BOOL play;

static void soundCompleted(SystemSoundID soundID, void *interval) {
    if(play) {
        [NSThread sleepForTimeInterval:(NSTimeInterval)interval];
        AudioServicesPlaySystemSound(soundID);
    } else {
        AudioServicesRemoveSystemSoundCompletion(soundID);
        AudioServicesDisposeSystemSoundID(soundID);
    }

}

@implementation Utilities

+ (SystemSoundID)createSystemSoundIDFromFile:(NSString *)fileName ofType:(NSString *)type {
    NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:type];
    SystemSoundID soundID;

    NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];

    AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
    return soundID;
}

+ (void)playAndRepeatSystemSoundID:(SystemSoundID)soundID interval:(NSTimeInterval)interval {
    play = YES
    AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL,
                                          soundCompleted, (void *)interval);
    AudioServicesPlaySystemSound(soundID);
}

+ (void)stopPlayingAndDisposeSystemSoundID {
    play = NO
}

@end

Sembra funzionare bene .. E per l'etichetta lampeggiante userò un NSTimer immagino.

È stato utile?

Soluzione

Un timer è più adatto per un intervallo rigorosamente definita. Si perderà la precisione se avete la vostra funzione stessa chiamata con un ritardo perché non è davvero sincronizzato per un intervallo di tempo. C'è sempre il tempo necessario per eseguire il metodo vero e proprio e che mette l'intervallo fuori.

Stick con una NSTimer, direi.

Altri suggerimenti

Giusto per aggiungere un po 'per le altre risposte, il caso di una chiamata ricorsiva sarebbe quando la chiamata potrebbe richiedere una quantità di tempo indeterminato - dire che si sta chiamando un servizio web più volte con piccole quantità di dati fino a quando si è finito. Ogni chiamata può richiedere una certa quantità di tempo indeterminato in modo da avere il codice non fare nulla fino a quando la chiamata web restituisce, poi il lotto successivo viene inviato fuori fino a non più dati rimangono da inviare e il codice non chiamare se stesso ancora una volta.

Dal momento che l'applicazione dipende dalla precisione di tempo (cioè di cui ha bisogno per eseguire una volta al secondo), il NSTimer sarebbe meglio. Ci vuole del tempo per il metodo stesso di eseguire, e un NSTimer sarebbe bene con che (a patto che il metodo prende meno di 1 secondo, se si chiama ogni secondo).

Per riprodurre ripetutamente il suono, è possibile impostare una richiamata di completamento e riprodurre il suono c'è:

SystemSoundID tickingSound;

...

AudioServicesAddSystemSoundCompletion(tickingSound, NULL, NULL, completionCallback, (void*) self);

...

static void completionCallback(SystemSoundID mySSID, void* myself) {
  NSLog(@"completionCallback");

  // You can use this when/if you want to remove the completion callback
  //AudioServicesRemoveSystemSoundCompletion(mySSID);

  // myself is the object that called set the callback, because we set it up that way above
  // Cast it to whatever object that is (e.g. MyViewController, in this case)
  [(MyViewController *)myself playSound:mySSID];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top