title: GCD serial queue with NSTimer, dispatch_sync doesn't wait for the NSTimer to complete
body: <p>I'm currently trying make a <code>queueHandler</code> that takes an object array as input for executing drive commands on a simple Double robot. I'm currently trying to use GCD in order to serially execute my functions, but when I'm using <code>dispatch_sync</code> on my queue in won't wait until the <code>NSTimer</code> has run its course, but will continue to try and execute the commands from the next object in my array.</p>
  
  <p>I have 3 functions, one which simply initializes an <code>NSMutableArray</code>(loadCommands) with 2 objects and runs the <code>queueHandler</code>, this is called when I toggle a switch. Then the <code>queueHandler</code> reads the variables from the objects(type, timing, queueNr) to determine what type of drive function will be executed and for how long. This I thought could be done in a switch statement, and I figured it would be great if the app could execute the function on the main thread(that is ok!) but it should wait until the <code>NSTimer</code> has run its course. I thought encapsulating the switch case with a dispatch_sync would solve this but it promptly skips to the next iteration in the loop and tries to execute the next function instead, which is drive backwards for 3 seconds.</p>
  
  <p>When I test this with a single object in the array the command will be executed without trouble. I suppose I'm locking up the main thread somehow. Would perhaps waiting for a return value from the function in the <code>@selector</code> in the <code>NSTimer</code> statement help?</p>
  
  <p>I've only played with Objective C for about 10 days, I'd appreciate any help I could get with this bit!</p>
  
  <pre><code>- (void)loadCommands {
      //create an objectArray and put 2 objects inside it.
  
      NSMutableArray *driveCommandsArray = [[NSMutableArray alloc]     initWithCapacity:4];
  
       //Command 1
      DRCommands *C1 = [[DRCommands alloc] init];
      C1.timing = 3;
      C1.type = 1;
      C1.queueNr = 1;
      [driveCommandsArray addObject:C1];
       //Command 2
      DRCommands *C2 = [[DRCommands alloc] init];
      C2.timing = 3;
      C2.type = 2;
      C2.queueNr = 2;
      [driveCommandsArray addObject:C2];
  
      //call queueHandler
      [self queueHandler:driveCommandsArray];
  
  }
  </code></pre>
  
  <p><strong>Queue handler:</strong></p>
  
  <pre><code>- (void)queueHandler: (NSMutableArray*) commandArray {
  
  //Now, I'm not sure what I'm doing here, I watched a tutorial that     
  //solved a vaguely similar problem and he put a dispatch_async before the 
  //dispatch_sync. I can't run the dispatch_sync clause inside the case
  //statement without this. 
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  
      NSLog(@"Inside handler!");
  
      unsigned long count;
      count = [commandArray count]; //retrieve length/number of objects from the array.
      unsigned long a;
  
       for (a = 0; a &lt; count;) {
       //run the loop until all objects has been managed.
  
          DRCommands* myObj = (DRCommands*)[commandArray objectAtIndex:a];
  
          //create 2 serial queues.
          dispatch_queue_t myQ1;
          myQ1 = dispatch_queue_create("myQ1", NULL);
          dispatch_queue_t myQ2;
          myQ2 = dispatch_queue_create("myQ2", NULL);
  
          int queueID = myObj.queueNr; //retrieve place in queue (not really used yet)
          int timeID = myObj.timing; //retrieve the amount of time the command shall be run through the NSTimer
          int typeID = myObj.type; //type of command
  
          NSLog(@"Inside for loop!");
  
          if (queueID == a+1) {
              a++;
  
              switch (typeID) {
  
                      {
                  case 1:
                      NSLog(@"inside case 1");
                      dispatch_sync(myQ1, ^{ //doesn't wait for NSTimer to finish, 
                                             //letting the Double drive forward for 3 seconds,
                                             //before resuming operations.
  
                          counter_ = timeID;
                          seconds.text = [NSString stringWithFormat:@"%d", counter_];
                          timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(jDriveForward) userInfo:nil repeats:YES];
  
                      });
                      break;
  
                  }
                      {
                  case 2:
                      NSLog(@"inside case 2");
                      dispatch_sync(myQ2, ^{
  
                          counter_ = timeID;
                          seconds.text = [NSString stringWithFormat:@"%d", counter_];
                          timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(jDriveBackward) userInfo:nil repeats:YES];
                      });
                      break;
                  }
                  //add more cases
                      {
                  default:
                      break;
                  }
              }
          }
  
          NSLog(@"Exited for loop, and count is %lu", a);
          }
      });
  }
  </code></pre>
  
  <p><strong>Drive commands:</strong></p>
  
  <pre><code>//Go forward X seconds.
  - (void)jDriveForward {
      shouldDriveForward_ = YES; //sets a condition which is recognized by a callback function to run the device forward.
      counter_ -= 1;
      seconds.text = [NSString stringWithFormat:@"%d", counter_];
  
      if (counter_ &lt;= 0) {
          [timer invalidate];
          shouldDriveForward_ = NO;
      }
  }
  
  //Go backwards X seconds.
  - (void)jDriveBackward {
      shouldDriveBackward_ = YES;
      counter_ -= 1;
      seconds.text = [NSString stringWithFormat:@"%d", counter_];
  
      if (counter_ &lt;= 0) {
          [timer invalidate];
          shouldDriveBackward_ = NO;
      }
  }
  </code></pre>
  
  <p><strong>Provided drive function from the experimental <a href="https://github.com/doublerobotics/Basic-Control-SDK-iOS/blob/master/DoubleBasicHelloWorld/DoubleBasicHelloWorld/DRViewController.m" rel="nofollow">API</a> I'm using</strong></p>
  
  <p>I'm using a "token" such as "shouldDriveForward_" inside the function driveDoubleShouldUpdate which is TRUE for the duration of an NSTimer. I must call my drive methods inside that function for the robot not to default to idle mode. So whenever it is true for X duration, the function for driving forwards or backwards is active.</p>
  
  <pre><code>- (void)doubleDriveShouldUpdate:(DRDouble *)theDouble {
  
      float drive = (driveForwardButton.highlighted) ? kDRDriveDirectionForward : ((driveBackwardButton.highlighted) ? kDRDriveDirectionBackward : kDRDriveDirectionStop);
      float turn = (driveRightButton.highlighted) ? 1.0 : ((driveLeftButton.highlighted) ? -1.0 : 0.0);
      [theDouble drive:drive turn:turn];
  
      //below are custom functions
      //The NSTimer I'm using keep the BOOL values below TRUE for X seconds, 
      //making the robot go forward/backward through this callback  
      //method, which I must use
      if(shouldDriveForward_ == YES) {
          [theDouble variableDrive:(float)1.0 turn:(float)0.0];
      }
      if(shouldDriveBackward_ == YES) {
          [theDouble variableDrive:(float)-1.0 turn:(float)0.0];
      }
  
  }
  </code></pre>