1

drawViewスレッドセーフで、ゲームアニメーションの短い期間の描画を行う機能があります。関数startAnimatingstopAnimating. バックグラウンド スレッドを通常の速度で呼び出す必要がありますdrawViewが、アニメーションが有効になっている間のみです。

では、スレッドを実行するためにstartAnimatingビューを呼び出すつもりでした。performSelectorInBackground:withObject:

スレッド通信を実行して描画スレッドを初期化する方法について少し混乱しています。具体的には、表示リンクメッセージを受信するように実行ループを設定し、最後に終了する必要があることをスレッドに通知し、実行ループをきれいに終了しますstopAnimating。メインスレッドから呼び出されます。drawViewが の後に呼び出されないようにしたいと思いstopAnimatingます。また、描画操作の途中で描画スレッドが突然キャンセルされないようにしたいと考えています。この種の質問に対する非常に貧弱な回答をオンラインでたくさん見てきました。

4

1 に答える 1

0

アップルのページを一晩中読んだ後、最終的に次のコードで解決しました。

// object members
NSThread *m_animationthread;
BOOL m_animationthreadrunning;

- (void)startAnimating
{
    //called from UI thread
    DEBUG_LOG(@"creating animation thread");
    m_animationthread = [[NSThread alloc] initWithTarget:self selector:@selector(animationThread:) object:nil];
    [m_animationthread start];
}

- (void)stopAnimating
{
    // called from UI thread
    DEBUG_LOG(@"quitting animationthread");
    [self performSelector:@selector(quitAnimationThread) onThread:m_animationthread withObject:nil waitUntilDone:NO];

    // wait until thread actually exits
    while(![m_animationthread isFinished])
        [NSThread sleepForTimeInterval:0.01];
    DEBUG_LOG(@"thread exited");

    [m_animationthread release];
    m_animationthread = nil;
}

- (void)animationThread:(id)object
{
    @autoreleasepool
    {
        DEBUG_LOG(@"animation thread started");
        m_animationthreadrunning = YES;

        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

        CADisplayLink *displaylink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkAction:)];
        [displaylink setFrameInterval:3];

        [displaylink addToRunLoop:runLoop forMode:NSDefaultRunLoopMode];

        while(m_animationthreadrunning)
        {
            [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
            DEBUG_LOG(@"runloop gap");
        }

        [displaylink removeFromRunLoop:runLoop forMode:NSDefaultRunLoopMode];

        DEBUG_LOG(@"animation thread quit");
    }
}

- (void)quitAnimationThread
{
    DEBUG_LOG(@"quitanimationthread called");
    m_animationthreadrunning = NO;
}

- (void)displayLinkAction:(CADisplayLink *)sender
{
    DEBUG_LOG(@"display link called");
    //[self drawView];
}

[self performSelector:@selector(quitAnimationThread) onThread:m_animationthread withObject:nil waitUntilDone:NO]単純に設定m_animationthreadrunning = NOするのではなく、この行を使用する理由stopAnimatingは、実行ループがタイムリーに返されない可能性があるためですが、セレクターを呼び出すと強制的に返されるためです。

于 2013-03-17T08:34:10.133 に答える