Question

Pour répéter un appel de méthode (ou envoyer un message, je suppose que le terme approprié est) tous les x secondes, est-il préférable d'utiliser un NSTimer (scheduledTimerWithTimeInterval de NSTimer: cible: sélecteur: UserInfo: répète: ) ou avoir la méthode elle-même appeler récursivement à la fin (en utilisant performSelector: withObject: afterDelay)? Ce dernier n'utilise pas un objet, mais peut-être son moins clair / lisible? De plus, juste pour vous donner une idée de ce que je fais, est juste une vue avec une étiquette qui compte à rebours jusqu'à minuit 12:00, et quand il arrive à 0, il clignote le temps (0:00:00) et jouer un bip sonore pour toujours.

Merci.

Edit: aussi, quelle serait la meilleure façon de jouer à plusieurs reprises une SystemSoundID (pour toujours)? Edit: Je fini par utiliser ceci pour jouer à l'infini le SystemSoundID:

// 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

Il semble fonctionner très bien .. Et pour l'étiquette clignote, je vais utiliser un NSTimer je suppose.

Était-ce utile?

La solution

Une minuterie est plus adapté à un intervalle strictement défini. Vous perdrez la précision si vous avez votre fonction elle-même appel avec un retard parce que son pas vraiment synced à un intervalle de temps. Il y a toujours le temps nécessaire pour exécuter la méthode proprement dite et qui met l'intervalle sur.

avec un NSTimer bâton, je dirais.

Autres conseils

Il suffit d'ajouter un peu aux autres réponses, le cas d'un appel récursif serait quand l'appel pourrait prendre une quantité inconnue de temps - dire que vous appelez un service Web à plusieurs reprises avec de petites quantités de données jusqu'à ce que vous avez terminé. Chaque appel peut prendre un certain temps indéterminé afin que vous avez le code ne rien faire jusqu'à ce que le retour de l'appel Web, puis le lot suivant est envoyé jusqu'à plus de données reste à envoyer et le code ne se remettent pas à nouveau.

Étant donné que votre application dépend de la précision du temps (à savoir qu'il doit exécuter une fois par seconde), le NSTimer serait mieux. Il faut un certain temps pour la méthode elle-même pour exécuter, et un NSTimer serait très bien avec ça (aussi longtemps que votre méthode prend moins de 1 seconde, si elle est appelée à chaque seconde).

Pour jouer à plusieurs reprises votre son, vous pouvez définir un rappel d'achèvement et le son y rejouer:

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];
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top