Pergunta

Para repetir uma chamada de método (ou enviar mensagem, acho que o termo apropriado é) a cada x Segundos, é melhor usar um NSTIMER (NSTIMER SGONDULEDTIMERWITHTIMEINTVAL: Target: Seletor: UserInfo: repete :) ou para que o método se chama recursivamente no final (usando o performações do performa: WithObject: AfterDelay)? O último não usa um objeto, mas talvez seja menos claro/legível? Além disso, apenas para lhe dar uma idéia do que estou fazendo, é apenas uma visão com uma etiqueta que conta com 12:00 meia -noite e, quando chegar a 0, isso piscará a hora (00:00:00) e reproduzir um sinal de bipe para sempre.

Obrigado.

EDIT: Além disso, qual seria a melhor maneira de tocar repetidamente um SystemSOUNDID (para sempre)? EDIT: Acabei usando isso para tocar o SystemSoundID para 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

Parece funcionar bem .. e para o rótulo piscando, vou usar um nstimer, eu acho.

Foi útil?

Solução

Um cronômetro é mais adequado para um intervalo estritamente definido. Você perderá a precisão se tiver sua função se chamar com um atraso, porque não é realmente sincronizado para um intervalo de tempo. Sempre há o tempo necessário para executar o próprio método real, o que divulga o intervalo.

Fique com um NSTIMER, eu diria.

Outras dicas

Apenas para adicionar um pouco às outras respostas, o caso de uma chamada recursiva seria quando a chamada pode levar um tempo desconhecido - digamos que você esteja ligando para um serviço da web repetidamente com pequenas quantidades de dados até que você termine. Cada chamada pode levar algum tempo desconhecido, para que você tenha o código não faça nada até que a chamada da web retorne, o próximo lote será enviado até que não haja mais dados para ser enviado e o código não se ligar novamente.

Como seu aplicativo depende da precisão do tempo (ou seja, ele precisa executar uma vez por segundo), o NSTIMER seria melhor. Leva algum tempo para o próprio método executar, e um NSTIMER ficaria bem com isso (desde que seu método demore menos de 1 segundo, se for chamado a cada segundo).

Para reproduzir repetidamente seu som, você pode definir um retorno de chamada de conclusão e reproduzir o som lá:

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];
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top