title: iOS Threads and making UI changes on the main thread
body: <p>I have the following <code>AcceptCallBack</code> method and was hoping to add an UIActivityIndicator while the method is running, hence the <code>[mvc performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES];</code>. <code>invoke</code> is the method which makes the UI changes. And then I have this line <code>[mvc performSelectorOnMainThread:@selector(hide) withObject:nil waitUntilDone:YES];</code> to remove the UIActivityIndicator. However what seem to happen is that invoke only gets called when <code>AcceptCallBack</code> has finished executing. Are <code>AcceptCallBack</code> and <code>invoke</code> not running on two different threads, therefore allowing them to run simultaneously?? </p>
  
  <pre><code>void AcceptCallBack(
                  CFSocketRef socket,
                  CFSocketCallBackType type,
                  CFDataRef address,
                  const void *data,
                  void *info)
  {
  NSLog(@"Start Receiving...");
  
  MasterViewController* mvc = (__bridge MasterViewController*)info;
  [mvc performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES];
  
  CFReadStreamRef readStream = NULL;
  CFWriteStreamRef writeStream = NULL;
  CFIndex bytes;
  UInt8 buffer[8192];
  UInt8 * fileData;
  UInt8 recv_len = 0;
  
  /* The native socket, used for various operations */
  CFSocketNativeHandle sock = *(CFSocketNativeHandle *) data;
  
  /* Create the read and write streams for the socket */
  CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock,
                               &amp;readStream, &amp;writeStream);
  
  if (!readStream || !writeStream) {
      close(sock);
      fprintf(stderr, "CFStreamCreatePairWithSocket() failed\n");
      return;
  }
  
  CFReadStreamOpen(readStream);
  CFWriteStreamOpen(writeStream);
  
  
  bool headerRead = false;
  int dataWritten = 0;
  NSMutableString* filename = NULL;
  
  
  NSMutableString * header = [[NSMutableString alloc] init];
  
  while (true) {
      memset(buffer, 0, sizeof(buffer));
      bytes = CFReadStreamRead(readStream, buffer, sizeof(buffer));
  
      recv_len += bytes;
  
      if (bytes &lt; 0) {
          fprintf(stderr, "CFReadStreamRead() failed: %d\n", (int)bytes);
          close(sock);
          return;
      }
      if (bytes == 0) {
          break;
      }
  
      if (!headerRead) {
          for (int b=0; b&lt;bytes; b++) {
              if (buffer[b] == '\n') {
                  headerRead = true;
                  NSLog(@"Header is: %@", header);
  
                  NSArray *listItems = [header componentsSeparatedByString:@":"];
                  filename = [[NSMutableString alloc] init];
                  [filename appendString:[listItems objectAtIndex:2]];
                  [filename replaceOccurrencesOfString:@"/" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [filename length])];
                  fileData = (UInt8*)malloc(sizeof(UInt8) * [[listItems objectAtIndex:3] intValue]);
  
                  b++;
                  memcpy(fileData, buffer + b, bytes - b);
                  dataWritten = bytes - b;
  
                  break;
              } else {
                  [header appendFormat:@"%c", buffer[b]];
              }
  
          }
      } else {
          memcpy(fileData + dataWritten, buffer, bytes);
          dataWritten += bytes;
      }
  
  }
  
  
  
  NSString* docFile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
  
  NSData * outputData = [[NSData alloc] initWithBytes:fileData length:dataWritten];
  if ([outputData writeToFile:docFile atomically:false] == YES) {
      NSLog(@"File received and successfully written out to file------------------------------");
  
      MasterViewController * thing = (__bridge MasterViewController*)info;
  
      [thing restClient:NULL loadedFile:docFile];
  
      NSString *destDir = @"/Slide2Me/";
      [[thing restClient] uploadFile:filename toPath:destDir
                       withParentRev:nil fromPath:docFile];
      [mvc performSelectorOnMainThread:@selector(hide) withObject:nil waitUntilDone:YES];
  
  
  
  
  } else {
      NSLog(@"Failed to write received data to file");
  }
  </code></pre>
  
  <p>}</p>
  
  <p><strong>EDIT</strong>
  So what I ended up doing to get my desired result is put all the above code in <code>dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)</code> and sandwich it with the changes I want to make on the main thread like so....</p>
  
  <pre><code>void AcceptCallBack(
                      CFSocketRef socket,
                      CFSocketCallBackType type,
                      CFDataRef address,
                      const void *data,
                      void *info)
  {
  
  
  NSLog(@"Start Receiving...");
  
  MasterViewController* mvc = (__bridge MasterViewController*)info;
  
  [mvc performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES];
  
  
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
        [the code above];
  
  });
  
  [mvc performSelectorOnMainThread:@selector(hide) withObject:nil waitUntilDone:YES];
  }
  </code></pre>