Вопрос

Чтобы повторить вызов метода (или отправку сообщения, я думаю, это подходящий термин) каждые Икс секунд, лучше ли использовать NSTimer (scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:) или рекурсивно вызывать метод в конце (используя PerformSelector:withObject:afterDelay)?Последний не использует объект, но, возможно, он менее понятен/читабельен?Кроме того, просто чтобы вы имели представление о том, что я делаю, это просто представление с меткой, которая ведет обратный отсчет до 12:00, а когда оно достигает 0, время мигает (00:00:00). и воспроизводить звуковой сигнал вечно.

Спасибо.

Редактировать:Кроме того, как лучше всего повторно воспроизводить SystemSoundID (навсегда)?Редактировать:В итоге я использовал это для постоянного воспроизведения 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

Вроде работает нормально..А для мигания метки, я думаю, я буду использовать NSTimer.

Это было полезно?

Решение

Таймер больше подходит на строго определенный интервал.Вы потеряете точность, если ваша функция будет вызывать себя с задержкой, потому что на самом деле это не так. синхронизировано к временному интервалу.Всегда есть время, необходимое для запуска самого метода, который выделяет интервал.

Я бы сказал, придерживайтесь NSTimer.

Другие советы

Чтобы добавить немного к другим ответам, случай рекурсивного вызова будет тогда, когда вызов может занять неизвестное количество времени - скажем, вы неоднократно вызываете веб-службу с небольшими объемами данных, пока не закончите.Каждый вызов может занять некоторое неизвестное количество времени, поэтому код ничего не делает, пока не вернется веб-вызов, затем отправляется следующий пакет до тех пор, пока не перестанут отправляться данные и код не вызовет себя снова.

Поскольку ваше приложение зависит от точности времени (т.он должен выполняться один раз в секунду), лучше использовать NSTimer.Для выполнения самого метода требуется некоторое время, и NSTimer с этим справится (если ваш метод занимает менее 1 секунды, если он вызывается каждую секунду).

Чтобы повторно воспроизводить звук, вы можете установить обратный вызов завершения и воспроизвести звук там:

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];
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top