1

X11 で GTK+ を使用する Linux では、「メイン ループ」と呼ばれるものがあります。メイン ループを開始すると、アプリケーションのメイン スレッドで実行されるタイマーが作成されます。そのタイマーをコールバック関数に設定すると、非常に優れたアプリケーション全体のタイマーが得られます。

これはそのためのサンプルコードです:

GMainLoop *loop;

if(!loop_running)
{
      display = XOpenDisplay( NULL );
      loop = g_main_loop_new(NULL, FALSE);
      g_timeout_add(1000, (GSourceFunc)callback, NULL); //1 sec laps   
      g_main_loop_run(loop);  //to stop use g_main_loop_quit ()  with the "loop" as arg
      loop_running=1;
}

Mac OS X 用の同様のアプリケーションを作成しようとしていますが、メイン ループの代わりに単純なタイマーを使用しています。

- (void) handleTimer: (NSTimer *) timer
{
    CopyDataToDB();
} // handleTimer

- (IBAction)startStopAction:(id)sender
{

   isOn=!isOn;
   if(isOn)
   {
       // Add our timers to the EventTracking loop       
       [[NSRunLoop currentRunLoop] addTimer: time forMode: NSEventTrackingRunLoopMode];

       // Add our timers to the ModelPanel loop       
       [[NSRunLoop currentRunLoop] addTimer: time forMode: NSModalPanelRunLoopMode];
   }
   else
   {
       [timer invalidate];
   }

}

それはあまりうまくいかないようです。タイマーは常にオフに設定されています。NSTimer でも試してみましたが、うまくいきませんでした。私はobjective-c、特にGUIアプリケーションにはあまり詳しくありません。

とにかく、Cocoa (Xcode を使用した object-c) でアプリケーション全体のタイマーを実装する方法はありますか?

ありがとう!

編集 NSTimer を使用する場合、これは実行時に発生するエラーです。

**[Session started at 2009-07-12 16:49:59 -0400.]
2009-07-12 16:50:02.784 MouseClick[1490:10b] Starting
2009-07-12 16:50:02.786 MouseClick[1490:10b] *** +[NSTimer scheduledTimerWithTimeInterval:selector:userInfo:repeats:]: unrecognized selector sent to class 0xa08d54c0
2009-07-12 16:50:02.787 MouseClick[1490:10b] *** +[NSTimer scheduledTimerWithTimeInterval:selector:userInfo:repeats:]: unrecognized selector sent to class 0xa08d54c0**

The Debugger has exited with status 0.

編集2

はい、分かりました。問題は、タイマーに「target:」を追加しなかったことです。今、タイマーをオフにすると、次のエラーが表示されます。

MouseClick(1652) malloc: * error for object 0x1645c0: double free * set a breakpoint in malloc_error_break to debug 

タイマーの解放は次のように行われます。

[timer invalidate]; 
[timer release]; 
timer = nil;
4

3 に答える 3

7

正確に何をしようとしているかによって異なります。ほとんどの場合、実行ループを台無しにして、単純にタイマーを設定するべきではありません。

const float framerate = 40;
const float frequency = 1.0f/framerate;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:frequency
    target:self selector:@selector(doSomething)
    userInfo:nil repeats:YES];

これで、doSomethingメソッドは毎秒約 40 回実行されます。できるだけ頻繁に何かを実行したい場合は、新しいスレッドを生成できます。

- (void) loop
{
    while (running)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        // Do something useful.
        [pool release];
    }
}

- (void) run
{
    run = YES;
    [NSThread detachNewThreadSelector:@selector(loop)
        toTarget:self withObject:nil];
}

もちろん、これでスレッドができました。これは同期を意味し、タイマーよりも頭痛の種が多いことを意味します。おっしゃる通り、何をしたいかによります。

そして、元の質問に答えると: はい、Cocoa アプリケーションにはおそらく GTK のものに似た「メイン ループ」があります。ループはすでに作成されているため、別のループを作成しても意味がありません。ただし、物事がどのように機能するかを理解しようとしているか、洗練された何かを実行しようとしている場合を除きます。詳細については、Threading Programming Guide のRun Loop Managementを参照してください。

イベントを単純に処理したい場合は、デフォルトの実行ループがそれを行います。ハンドラを実装するだけです。ボタンなどに接続されたメソッド。定期的に何かをしたい場合 (アニメーションの更新など)、タイマー ( NSTimer) を設定します。デフォルトの実行ループが時間を処理し、適切なセレクターを何度でも呼び出します。

于 2009-07-12T20:24:51.910 に答える
1

タイマーは、任意のオブジェクトをターゲットとして設定できます。また、目的のターゲットにタイマーを「アタッチ」するための適切なエントリ ポイントがいくつかあります。

timeこの文脈でどこから来たのかよくわかりません。+timerWithTimeInterval:invocation:repeats:しかし、おそらく(NSTimerで)作成されたタイマーだと思いますか?そうでない場合、その特定のメソッドは、使用するのに非常に便利なタイマーを提供するはずです。

于 2009-07-12T20:24:22.363 に答える
0

NSTimer を試したとき、タイマーを保持しましたか? タイマーが呼び出すオブジェクトも保持するのはどうですか...

于 2009-07-12T20:36:06.863 に答える