3

ユーザーは、スワイプジェスチャでアニメーションを開始できます。アニメーションへの重複呼び出しをブロックして、アニメーションが開始されると、完了するまで再開できないようにします。これは、ユーザーが誤って複数回スワイプした場合に発生する可能性があります。

ほとんどの人BOOL isAnimatingFlagは、下に示すようにブールフラグ()を使用してこの制御を実現していると思います。私はこれまでアプリでこのようなことを何度も行ってきましたが、アニメーションはブロックを使用しており、アニメーションの完成がどのスレッドであるかが不明なため、フラグが意図した値を確実に持つかどうかについて100%確信することはありません。ブロックが実行されています。

この方法(重複するアニメーションをブロックする方法)は、マルチスレッド実行に対して信頼できますか?

/* 'atomic' doesn't 
* guarantee thread safety
* I've set up my flag as follows:
* Does this look correct for the intended usage?
*/
@property (assign, nonatomic) BOOL IsAnimatingFlag;

//…

@synthesize IsAnimatingFlag

//…

-(void)startTheAnimation{

// (1) return if IsAnimatingFlag is true
if(self.IsAnimatingFlag == YES)return;

/* (2) set IsAnimatingFlag to true
* my intention is to prevent duplicate animations
* which may be caused by an unwanted double-tap
*/
self.etiIsAnimating = YES;


    // (3) start a new animation
    [UIView animateWithDuration:0.75 delay:0.0 options:nil animations:^{

    // animations would happen here...

    } completion:^(BOOL finished) {

    // (4) reset the flag to enable further animations
        self.IsAnimatingFlag = NO;
    }];
}
4

3 に答える 3

4

ユーザーがジェスチャーを複数回トリガーしたくない場合は、ジェスチャーを無効にします

- (void)startTheAnimation:(id)sender
{
  [sender setEnabled:NO];

  [UIView animateWithDuration:0.75 delay:0.0 options:nil animations:^{

    // animations would happen here...

  } completion:^(BOOL finished) {
    [sender setEnabled:YES];
  }];
}

アップデート

ジェスチャにもenabledプロパティがあるため、ボタンであるかのように同じアイデアを使用して、有効な状態を変更できます。

于 2013-03-01T14:36:45.320 に答える
2

アニメーション完了ブロックは常にメインスレッドで実行されます。

UIViewクラスリファレンスの例では[view removeFromSuperview]、ブロックから直接呼び出されていることがわかります。これは、UI関連のメソッドを安全に呼び出すことができる唯一のスレッドであるため、完了ブロックがメインスレッドで実行されることを意味します。

startTheAnimationしたがって、メインスレッドからのみ呼び出す場合は、すべて問題ありません。そうでない場合は、UI関連のメソッドを呼び出すため、とにかくメインスレッドにディスパッチする必要があります。

startTheAnimationメインスレッド以外のスレッドから呼び出す必要がある場合は、次のようにすることができます。

-(void)startTheAnimation{
    dispatch_async(dispatch_get_main_queue(), ^{
        // Your code here
    });
}

もちろん、ユーザーエクスペリエンスの観点からは、たとえば、ボタンを無効にしたり、アニメーションが進行中であることを示すために他の方法でUIを変更したりすることをお勧めします。ただし、それはすべて同じコードです。必要なことは何でも、アニメーションを開始する前に最初に無効にし、終了後に再度有効にする必要があります。

于 2013-03-01T14:44:18.350 に答える
0

このメソッドを呼び出す場合は、dispatch_onceGCD関数を使用してみてください。

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    [myThingy startTheAnimation];
});
于 2013-03-01T14:36:42.043 に答える