0

Ok。タイトルがわかりにくいかもしれません。

私が実装したロジックはこんな感じです。

  • アプリケーションに検出器があります(自転車の速度計のように-動く矢印)
  • ユーザーがスキャン開始ボタンをタップすると、最初のメソッドが実行されます。
  • NowStartMovementsは、停止するランダムな回転と乱数を決定します
  • 検出器には1から10の数字があります。
  • 今まではすべてうまくいきました。
  • 次のコードはエラーがありません。
  • 矢印は完全に移動し、適切な位置で停止します(ランダムに決定)

  • しかし、問題は「ムーブメントのforループを実装した」ということです。

  • したがって、forループの実行中は、ユーザー操作は有効になりません。

実装したコードも追加しました。


-(IBAction)ScanStart:(id)sender
{
btnScan.enabled=NO; stopThroughButtons=NO; shouldNeedleGoRightSide=YES; currentNeedleValue=1; nxtNeedleValue=2;
[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(nowStartMovements) userInfo:nil repeats:NO];
}

-(void)nowStartMovements{
totalRotations=arc4random()%9; if(totalRotations<3) totalRotations+=3;
currentRotation=0;stopValue=arc4random()%11; if(stopValue<1)stopValue=1;
int totalMovements=(totalRotations-1)*10 + ( (totalRotations%2==0)?10-stopValue:stopValue ), i;
for(i=0;i<totalMovements;i++){
    if (stopThroughButtons) return;
    [NSThread detachNewThreadSelector:@selector(moveNeedle) toTarget:self withObject:nil];
    usleep(200000);
}
}

-(void)moveNeedle{
spinAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
double fromValue=[[arrayOfFloatValues objectAtIndex:currentNeedleValue-1] doubleValue];
double toValue=[[arrayOfFloatValues objectAtIndex:nxtNeedleValue-1] doubleValue];
spinAnimation.duration=0.2;
spinAnimation.fromValue=[NSNumber numberWithFloat:fromValue];
spinAnimation.toValue = [NSNumber numberWithFloat:toValue];
[imgNideel.layer addAnimation:spinAnimation forKey:@"spinAnimation"];
[NSThread detachNewThreadSelector:@selector(MoveActualNeedle) toTarget:self withObject:nil];
}

-(void)MoveActualNeedle{
if(shouldNeedleGoRightSide){        
    if(currentNeedleValue<9) { currentNeedleValue++; nxtNeedleValue++;}
    else { shouldNeedleGoRightSide=NO; currentNeedleValue=10; nxtNeedleValue=9;
}
    imgNideel.transform=CGAffineTransformMakeRotation([[arrayOfFloatValues objectAtIndex:currentNeedleValue-1] doubleValue]);
} else {
    if(currentNeedleValue>2){ currentNeedleValue--; nxtNeedleValue--;} 
    else { shouldNeedleGoRightSide=YES; currentNeedleValue=1; nxtNeedleValue=2;
}
    imgNideel.transform=CGAffineTransformMakeRotation([[arrayOfFloatValues objectAtIndex:currentNeedleValue-1] doubleValue]);
}   
}
4

2 に答える 2

2

ロジックを書き直して、usleep ではなく、スリープを行っている Timer になるようにする必要があります。繰り返し可能なタイマーのすべての反復が for ループ内にあることを実行するように、関数を書き直してください。

問題は、メイン スレッドで for ループがスリープ状態になっていることです。タイマーを使用し、繰り返しを YES に設定すると、これは本質的に実行中の for/sleep パターンを実行します。停止したい場合は[timer invalidate]を呼び出します。

于 2009-09-23T20:35:10.193 に答える
1

理想的には、タイマーを使用して針の動きをスケジュールします。既存のコードに対する最も簡単な解決策は次のとおりです。

  • で、にStartScan変更-scheduledTimerWithTimeInterval:-performSelectorInBackground:

  • で、にnowStartMovements変更-detachNewThreadSelector:-performSelectorOnMainThread:

この方法ではusleep、バックグラウンド スレッドで発生し、メイン スレッドをブロックしません。メインスレッドがブロックされている限り、UI はフリーズします。

于 2009-09-23T22:30:24.297 に答える