iPhone开发人员--性能选择器:withObject:afterDelay还是NSTimer?

iPhone开发人员--性能选择器:withObject:afterDelay还是NSTimer?,iphone,nstimer,tail-recursion,repeat,Iphone,Nstimer,Tail Recursion,Repeat,要每x秒重复一次方法调用(或消息发送,我想合适的术语是),最好使用NSTimer(NSTimer的scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:)还是让方法在最后递归地调用自己(使用performSelector:withObject:afterDelay)?后者不使用对象,但可能不太清晰/可读?另外,为了让你知道我在做什么,这只是一个带有标签的视图,它倒计时到午夜12:00,当它达到0时,它将闪烁时间(00:00

要每x秒重复一次方法调用(或消息发送,我想合适的术语是),最好使用NSTimer(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
//Utilities.h
#进口
#进口
静态void soundCompleted(SystemSoundID soundID,void*我自己);
@接口实用程序:NSObject{
}
+(SystemSoundID)createSystemSoundIDFromFile:(NSString*)类型的文件名:(NSString*)类型;
+(无效)播放和重复系统声音ID:(系统声音ID)声音ID;
+(无效)停止铺设和处置系统;
@结束
//公用事业
#导入“Utilities.h”
静态布尔播放;
静态void soundCompleted(SystemSoundID soundID,void*间隔){
如果(玩){
[NSThread sleepForTimeInterval:(NSTimeInterval)interval];
AudioServicesPlaySystemSound(soundID);
}否则{
AudioServicesRemoveSystemSoundCompletion(声音ID);
AudioServicesDisposeSystemSoundID(soundID);
}
}
@实现实用程序
+(SystemSoundID)createSystemSoundIDFromFile:(NSString*)类型的文件名:(NSString*)类型{
NSString*path=[[NSBundle mainBundle]pathForResource:type的文件名:type];
系统声音ID;
NSURL*filePath=[NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)文件路径和soundID);
返回声音ID;
}
+(void)播放和重复系统声音ID:(SystemSoundID)声音ID间隔:(NSTimeInterval)间隔{
播放=是
AudioServicesAddSystemSoundCompletion(声音ID,NULL,NULL,
声音完成,(void*)间隔;
AudioServicesPlaySystemSound(soundID);
}
+(无效)停止铺设和处理SystemsSoundID{
播放=否
}
@结束

好像很好用。。对于标签闪烁,我想我将使用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];
}

在其他答案的基础上再补充一点,递归调用的情况是,调用可能需要未知的时间量——比如说,使用少量数据重复调用web服务,直到完成为止。每次调用可能需要一些未知的时间,因此在web调用返回之前,您让代码什么也不做,然后发送下一批,直到没有更多的数据需要发送,代码不会再次调用自己。

这有助于对比这两种方法。