title: NSOperation subclass not calling delegate methods and NSOperationQueue not waiting until finished
body: <p>I use this piece of code to create some NSOperations and add them to a queue:</p>
  
  <pre><code>HUD = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
          //HUD.labelText = @"Downloading..";
          //HUD.dimBackground = YES;
  
          /* Operation Queue init  */
          NSOperationQueue *queue = [NSOperationQueue new];
  
          // Spawn request operations &amp; add them to queue
          SoapRequestOperation *operation = [[SoapRequestOperation alloc] initWithRequest:@"&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt; &lt;soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt; &lt;soap:Body&gt; &lt;Categories xmlns=\"http://tempuri.org/\"&gt; &lt;UID&gt;string&lt;/UID&gt; &lt;Username&gt;string&lt;/Username&gt; &lt;Password&gt;string&lt;/Password&gt; &lt;/Categories&gt;      &lt;/soap:Body&gt; &lt;/soap:Envelope&gt;" andValue:@"Categories"];
  
          [queue addOperation:operation];
  
          operation = [[SoapRequestOperation alloc] initWithRequest:@"&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt; &lt;soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt; &lt;soap:Body&gt; &lt;Currencies xmlns=\"http://tempuri.org/\"&gt; &lt;UID&gt;string&lt;/UID&gt; &lt;Username&gt;string&lt;/Username&gt; &lt;Password&gt;string&lt;/Password&gt; &lt;/Currencies&gt;      &lt;/soap:Body&gt; &lt;/soap:Envelope&gt;" andValue:@"Currencies"];
  
          [queue addOperation:operation];
  
          operation = [[SoapRequestOperation alloc] initWithRequest:@"&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt; &lt;soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt; &lt;soap:Body&gt; &lt;Nominals xmlns=\"http://tempuri.org/\"&gt;   &lt;UID&gt;string&lt;/UID&gt; &lt;Username&gt;string&lt;/Username&gt; &lt;Password&gt;string&lt;/Password&gt; &lt;/Nominals&gt; &lt;/soap:Body&gt; &lt;/soap:Envelope&gt;" andValue:@"Nominals"];
  
          [queue addOperation:operation];
  
          operation = [[SoapRequestOperation alloc] initWithRequest:@"&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt; &lt;soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt; &lt;soap:Body&gt; &lt;Projects xmlns=\"http://tempuri.org/\"&gt;   &lt;UID&gt;string&lt;/UID&gt; &lt;Username&gt;string&lt;/Username&gt; &lt;Password&gt;string&lt;/Password&gt; &lt;/Projects&gt;        &lt;/soap:Body&gt; &lt;/soap:Envelope&gt;" andValue:@"Projects"];
  
          [queue addOperation:operation];
  
          operation = [[SoapRequestOperation alloc] initWithRequest:@"&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt; &lt;soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt; &lt;soap:Body&gt; &lt;Register xmlns=\"http://tempuri.org/\"&gt;   &lt;UID&gt;string&lt;/UID&gt; &lt;Username&gt;string&lt;/Username&gt; &lt;Password&gt;string&lt;/Password&gt; &lt;OrganisationCode&gt;string&lt;/OrganisationCode&gt; &lt;/Register&gt; &lt;/soap:Body&gt; &lt;/soap:Envelope&gt;" andValue:@"Register"];
  
          [queue addOperation:operation];
  
          [queue waitUntilAllOperationsAreFinished];
  
          [self reloadTableData];
  
          HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]];
          HUD.mode = MBProgressHUDModeCustomView;
          [HUD hide:YES afterDelay:2];
  </code></pre>
  
  <p>This is the .m file for my NSOperation subclass:</p>
  
  <pre><code>#import "SoapRequestOperation.h"
  #import "Currency.h"
  #import "Category.h"
  #import "Project.h"
  #import "Constants.h"
  
  @implementation SoapRequestOperation
  
  @synthesize request, value;
  
  -(id) initWithRequest:(NSString *)l_Request andValue:(NSString *)l_Value{
      if (self = [super init]) {
          /* do most of initialization */
          self.request = l_Request;
          self.value = l_Value;
          xmlBlock = 0;
          appDelegate = [[UIApplication sharedApplication] delegate];
      }
      return(self);
  }
  
  - (void) main {
      if ([value isEqualToString:@"Category"]){
          xmlBlock = CATEGORY;
      }
      else if ([value isEqualToString:@"Currency"]){
          xmlBlock = CURRENCY;
      }
      else if ([value isEqualToString:@"Nominal"]){
          xmlBlock = NOMINAL;
      }
      else if ([value isEqualToString:@"Project"]){
          xmlBlock = PROJECT;
      }
      else {
          xmlBlock = REGISTER;
      }
  
      NSString *soapMsg = request;
      //---print it to the Debugger Console for verification---
      NSLog(@"%@", soapMsg);
      NSURL *url = [NSURL URLWithString:
                    @"http://www.$^$%£%@%^£.co.uk/$$^$^£$^£.asmx"];
      NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
      //---set the headers---
      NSString *msgLength = [NSString stringWithFormat:@"%d",
                             [soapMsg length]];
      [req addValue:@"text/xml; charset=utf-8"
  forHTTPHeaderField:@"Content-Type"];
      [req addValue:[NSString stringWithFormat:@"http://tempuri.org/%@", value]
  forHTTPHeaderField:@"SOAPAction"];
      [req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
      //---set the HTTP method and body---
      [req setHTTPMethod:@"POST"];
      [req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
      //[activityIndicator startAnimating];
      conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
      if (conn) {
          webData = [NSMutableData data];
      }
  }
  
  -(void) connection:(NSURLConnection *) connection
  didReceiveResponse:(NSURLResponse *) response {
      [webData setLength: 0];
  }
  
  -(void) connection:(NSURLConnection *) connection
      didReceiveData:(NSData *) data {
      [webData appendData:data];
  }
  
  -(void) connection:(NSURLConnection *) connection
    didFailWithError:(NSError *) error {
  
  }
  
  -(void) connectionDidFinishLoading:(NSURLConnection *) connection {
      NSLog(@"DONE. Received Bytes: %d", [webData length]);
      NSString *theXML = [[NSString alloc]
                          initWithBytes: [webData mutableBytes]
                          length:[webData length]
                          encoding:NSUTF8StringEncoding];
      //---shows the XML---
      NSLog(@"%@", theXML);
  
      xmlParser = [[NSXMLParser alloc] initWithData: webData];
      [xmlParser setDelegate: self];
      [xmlParser setShouldResolveExternalEntities:YES];
      [xmlParser parse];
  
  }
  
  //---when the start of an element is found---
  -(void) parser:(NSXMLParser *) parser
  didStartElement:(NSString *) elementName
    namespaceURI:(NSString *) namespaceURI
   qualifiedName:(NSString *) qName
      attributes:(NSDictionary *) attributeDict {
      currentElement = [elementName copy];
  
      //Category
      if( [currentElement isEqualToString:@"Item"])
      {
          category = [[NSMutableDictionary alloc] init];
          categoryName = [[NSMutableString alloc] init];
      }
  
      //Currency
      if ([currentElement isEqualToString: @"Currency"]) {
          currency = [[NSMutableDictionary alloc] init];
          countryName = [[NSMutableString alloc] init];
          currencyName = [[NSMutableString alloc] init];
          currencyUnit = [[NSMutableString alloc] init];
          shortName = [[NSMutableString alloc] init];
      }
  
      //Nominal
      if( [currentElement isEqualToString:@"Nominal"])
      {
          nominal = [[NSMutableDictionary alloc] init];
          name = [[NSMutableString alloc] init];
          description = [[NSMutableString alloc] init];
          paid = [[NSMutableString alloc] init];
      }
  
      //Project
      if( [currentElement isEqualToString:@"Project"])
      {
          project = [[NSMutableDictionary alloc] init];
          projectName = [[NSMutableString alloc] init];
          projectDescription = [[NSMutableString alloc] init];
      }
  
      //Register
      if( [currentElement isEqualToString:@"RegisterResult"])
      {
          elementFound = YES;
      }
  
  }
  
  -(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string
  {
      //Category
      if (xmlBlock == CATEGORY){
          if ([currentElement isEqualToString: @"Item"]){
              [categoryName appendString:string];
          }
      }
  
      //Currency
      if (xmlBlock == CURRENCY){
          if ([currentElement isEqualToString: @"CountryName"]){
              [countryName appendString:string];
          }
          else if ([currentElement isEqualToString: @"CurrencyName"]){
              [currencyName appendString:string];
          }
          else if ([currentElement isEqualToString: @"Unit"]){
              [currencyUnit appendString:string];
          }
          else if ([currentElement isEqualToString: @"ShortName"]){
              [shortName appendString:string];
          }
      }
  
      //Nominal
      if ([currentElement isEqualToString: @"Name"] &amp;&amp; xmlBlock == NOMINAL){
          [name appendString:string];
      }
      else if ([currentElement isEqualToString: @"Description"] &amp;&amp; xmlBlock == NOMINAL){
          [description appendString:string];
      }
      else if ([currentElement isEqualToString: @"Paid"]){
          [paid appendString:string];
      }
  
      //Project
      if (xmlBlock == PROJECT) {
          if ([currentElement isEqualToString: @"Name"]){
              [projectName appendString:string];
          }
          else if ([currentElement isEqualToString: @"Description"]){
              [projectDescription appendString:string];
          }
      }
  
      //Register
      if (xmlBlock == REGISTER &amp;&amp; elementFound){
          registerVal = string;
      }
  }
  
  //---when the end of element is found---
  -(void)parser:(NSXMLParser *)parser
  didEndElement:(NSString *)elementName
   namespaceURI:(NSString *)namespaceURI
  qualifiedName:(NSString *)qName
  {    
      if ([elementName isEqualToString:@"Item"])
      {
          // save values to an item, then store that item into the array...
          [category setObject:categoryName forKey:@"categoryName"];
  
          [categories addObject:[category copy]];
  
          Category *c = [[Category alloc] init];
          c.categoryName = categoryName;
          c.totalValue = @"0.00";
          [appDelegate.categories addObject:c];
  
          NSLog(@"%d", [appDelegate.categories count]);
      }
  
      //Currency
      if ([elementName isEqualToString: @"Currency"]) {
          // save values to an item, then store that item into the array...
          [currency setObject:countryName forKey:@"countryName"];
          [currency setObject:currencyName forKey:@"currencyName"];
          [currency setObject:currencyUnit forKey:@"unit"];
          [currency setObject:shortName forKey:@"shortName"];
  
          [currencies addObject:[currency copy]];
  
          Currency *c = [[Currency alloc] init];
          c.totalValue = @"0.00";
          c.countryName = countryName;
          c.currencyName = currencyName;
          double myDouble = [currencyUnit doubleValue];
          c.unit = myDouble;
          c.shortName = shortName;
  
          [appDelegate.currencies addObject:c];
  
          NSLog(@"%d", [appDelegate.currencies count]);
  
      }
  
      //Nominal
      if ([elementName isEqualToString:@"Nominal"])
      {
          // save values to an item, then store that item into the array...
          [nominal setObject:name forKey:@"name"];
          [nominal setObject:description forKey:@"description"];
          [nominal setObject:paid forKey:@"paid"];
  
          [nominals addObject:[nominal copy]];
  
          NSLog(@"%d", [nominals count]);
  
      }
  
      if ([elementName isEqualToString:@"Project"])
      {
          // save values to an item, then store that item into the array...
          [project setObject:projectName forKey:@"projectName"];
          [project setObject:projectDescription forKey:@"projectDescription"];
  
          [projects addObject:[project copy]];
  
          Project *p = [NSEntityDescription
                        insertNewObjectForEntityForName:@"Project"
                        inManagedObjectContext:appDelegate.managedObjectContext];
          [p setValue:projectName forKey:@"name"];
          [p setValue:@"0.00" forKey:@"totalValue"];
          NSError *error;
          if (![appDelegate.managedObjectContext save:&amp;error]) {
              NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
          }
          [appDelegate.projects addObject:p];
  
          NSLog(@"%d", [appDelegate.currencies count]);
      }
  
      if ([elementName isEqualToString:@"RegisterResult"])
      {
          if ([registerVal isEqualToString:@"true"]){
              boolRegister = YES;
          }
          else {
              boolRegister = NO;
          }
  
          NSLog(@"BOOL = %@", (boolRegister ? @"YES" : @"NO"));
  
          elementFound = FALSE;
      }
  }
  </code></pre>
  
  <p>Unfortunately, the NSURLConnection and NSXMLParser delegate methods are not being called (everything is as it should be in the header file).  And I'm not sure I fully understand the line:</p>
  
  <pre><code>[queue waitUntilAllOperationsAreFinished];
  </code></pre>
  
  <p>Should this not cause the calling thread to wait until all the operations are completed?  I have a feeling this line isn't working due to the faults with the NSOperation subclass itself?</p>
  
  <p>Can anyone help me out here?</p>
  
  <p>Thanks a lot,</p>
  
  <p>Jack</p>