views:

102

answers:

3

Ok. I know the title may be confusing.

Logic That I have implemented is something like this.

  • There is an detector in application ( like bike speedometer - moving arrow )
  • When user taps start scan button - first method executes.
  • NowStartMovements decides random rotations & random number to stop
  • There are 1 to 10 numbers on detector.
  • Every thing works fine up to now.
  • Following code is error free.
  • Arrow moves perfectly & stops at proper position ( decided randomly )

  • But the problem is " I have implemented for loop for the movements "

  • So, while executing for loop, User interaction isn't enabled.

I have also added the code that I have implemented.


-(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]);
} 
}
A: 

Is there any BackgroundWorker - like structure?

Aggelos Mpimpoudis
No, Nothing. Any other details required - sir?
sugar
+2  A: 

You will need to rewrite your logic so it is the Timer that is doing the sleeping, not the usleep. Rewrite your function so that every iteration of the repeatable timer does what is in the for loop.

The problem is the for loop is sleeping on the main thread. If you use a timer and set repeats to YES, then this essesntially does the for/sleep pattern you are doing. When you want to stop it call [timer invalidate];

coneybeare
I have implemented according to your suggestions.
sugar
+1  A: 

Ideally, you'd use a timer to schedule the needle movements. The quickest solution to your existing code is this:

  • In StartScan, change -scheduledTimerWithTimeInterval: to -performSelectorInBackground:

  • In nowStartMovements, change -detachNewThreadSelector: to -performSelectorOnMainThread:

This way, the usleep happens on a background thread and doesn't block the main thread. The UI will be frozen as long as the main thread is blocked.

Darren
correct. exact.
sugar