10

要每x秒重复一次方法调用(或消息发送,我想合适的术语是),最好使用 NSTimer(NSTimer 的 scheduleTimerWithTimeInterval:target:selector:userInfo:repeats:) 还是让该方法在结束(使用 performSelector:withObject:afterDelay)?后者不使用对象,但可能不太清晰/可读?另外,只是为了让您了解我在做什么,它只是一个带有标签的视图,该标签倒计时到午夜 12:00,当它到达 0 时,它会闪烁时间 (00:00:00)并永远播放哔声。

谢谢。

编辑:另外,重复播放 SystemSoundID (forever) 的最佳方式是什么?编辑:我最终使用它来永远播放 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。

4

3 回答 3

6

计时器更适合严格定义的间隔。如果您的函数调用本身有延迟,您将失去准确性,因为它并没有真正同步到时间间隔。运行实际方法本身也总是需要花费时间,这会将时间间隔排除在外。

我会说,坚持使用 NSTimer。

于 2009-09-29T00:48:12.970 回答
2

只是为其他答案添加一点,递归调用的情况是调用可能需要未知的时间 - 假设您正在使用少量数据重复调用 Web 服务,直到您完成。每次调用可能需要一些未知的时间,因此您可以让代码在 Web 调用返回之前什么都不做,然后发送下一批,直到没有更多数据需要发送并且代码不会再次调用自身。

于 2009-09-29T04:57:14.483 回答
1

由于您的应用程序依赖于时间精度(即它需要每秒执行一次),因此 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];
}
于 2009-09-29T01:52:46.610 回答