代码之家  ›  专栏  ›  技术社区  ›  mk12

iphone dev-performselector:withobject:afterdelay还是nstimer?

  •  10
  • mk12  · 技术社区  · 15 年前

    重复方法调用(或消息发送,我想适当的术语是)每 X 秒,使用nstimer(nstimer的scheduledTimerWithTimeInterval:Target:Selector:UserInfo:Repeats:)还是让方法在末尾递归地调用自身(使用performSelector:WithObject:AfterDelay)?后者不使用对象,但可能不太清晰/可读?另外,为了让你知道我在做什么,它只是一个带有标签的视图,倒数到午夜12:00,当它变为0时,它会闪烁时间(00:00:00),并永远播放哔哔声。

    谢谢。

    编辑:还有,重复播放系统声音ID(永远)的最佳方法是什么? 编辑:我最终用这个来永远播放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
    

    似乎工作得很好。对于标签闪烁,我想我会用一个计时器。

    3 回复  |  直到 15 年前
        1
  •  6
  •   Nick Bedford    15 年前

    计时器更适合于严格定义的间隔。如果函数调用本身带有延迟,则会丢失准确性,因为它实际上不是 同步的 到一个时间间隔。运行实际的方法本身也需要一定的时间,这就消除了时间间隔。

    我会说,坚持用计时器。

        2
  •  2
  •   Kendall Helmstetter Gelner    15 年前

    只需在其他答案中添加一点,递归调用的情况是,调用可能需要一段未知的时间——比如说,您正在使用少量数据反复调用Web服务,直到完成为止。每次调用可能需要一些未知的时间,因此,在Web调用返回之前,代码不做任何操作,然后发送下一批数据,直到不再发送数据,代码不再调用自己。

        3
  •  1
  •   Elliot    15 年前

    由于您的应用程序依赖于时间准确性(即它需要每秒执行一次),因此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];
    }