10

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

正常に動作するようです..そして、ラベルの点滅には、私が推測する NSTimer を使用します。

4

3 に答える 3

6

タイマーは、厳密に定義された間隔により適しています。実際には時間間隔に同期されていないため、関数自体を遅延して呼び出すと精度が失われます。実際のメソッド自体を実行するのにかかる時間も常にあり、間隔が空けられます。

NSTimerに固執してください。

于 2009-09-29T00:48:12.970 に答える
2

他の回答に少し追加するために、再帰呼び出しのケースは、呼び出しに不明な時間がかかる場合です-たとえば、少量のデータでWebサービスを繰り返し呼び出して、終了するまで. 各呼び出しには不明な時間がかかる場合があるため、Web 呼び出しが戻るまでコードに何も行わせず、送信するデータがなくなるまで次のバッチを送信し、コードが再度呼び出されないようにします。

于 2009-09-29T04:57:14.483 に答える
1

アプリケーションは時間の精度に依存するため (つまり、1 秒に 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 に答える