0

我使用这段代码来创建一些 NSOperations 并将它们添加到队列中:

HUD = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
        //HUD.labelText = @"Downloading..";
        //HUD.dimBackground = YES;

        /* Operation Queue init  */
        NSOperationQueue *queue = [NSOperationQueue new];

        // Spawn request operations & add them to queue
        SoapRequestOperation *operation = [[SoapRequestOperation alloc] initWithRequest:@"<?xml version=\"1.0\" encoding=\"utf-8\"?> <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/\"> <soap:Body> <Categories xmlns=\"http://tempuri.org/\"> <UID>string</UID> <Username>string</Username> <Password>string</Password> </Categories>      </soap:Body> </soap:Envelope>" andValue:@"Categories"];

        [queue addOperation:operation];

        operation = [[SoapRequestOperation alloc] initWithRequest:@"<?xml version=\"1.0\" encoding=\"utf-8\"?> <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/\"> <soap:Body> <Currencies xmlns=\"http://tempuri.org/\"> <UID>string</UID> <Username>string</Username> <Password>string</Password> </Currencies>      </soap:Body> </soap:Envelope>" andValue:@"Currencies"];

        [queue addOperation:operation];

        operation = [[SoapRequestOperation alloc] initWithRequest:@"<?xml version=\"1.0\" encoding=\"utf-8\"?> <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/\"> <soap:Body> <Nominals xmlns=\"http://tempuri.org/\">   <UID>string</UID> <Username>string</Username> <Password>string</Password> </Nominals> </soap:Body> </soap:Envelope>" andValue:@"Nominals"];

        [queue addOperation:operation];

        operation = [[SoapRequestOperation alloc] initWithRequest:@"<?xml version=\"1.0\" encoding=\"utf-8\"?> <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/\"> <soap:Body> <Projects xmlns=\"http://tempuri.org/\">   <UID>string</UID> <Username>string</Username> <Password>string</Password> </Projects>        </soap:Body> </soap:Envelope>" andValue:@"Projects"];

        [queue addOperation:operation];

        operation = [[SoapRequestOperation alloc] initWithRequest:@"<?xml version=\"1.0\" encoding=\"utf-8\"?> <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/\"> <soap:Body> <Register xmlns=\"http://tempuri.org/\">   <UID>string</UID> <Username>string</Username> <Password>string</Password> <OrganisationCode>string</OrganisationCode> </Register> </soap:Body> </soap:Envelope>" 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];

这是我的 NSOperation 子类的 .m 文件:

#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"] && xmlBlock == NOMINAL){
        [name appendString:string];
    }
    else if ([currentElement isEqualToString: @"Description"] && 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 && 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:&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;
    }
}

不幸的是,没有调用 NSURLConnection 和 NSXMLParser 委托方法(一切都在头文件中)。而且我不确定我是否完全理解这条线:

[queue waitUntilAllOperationsAreFinished];

这不应该导致调用线程等待所有操作完成吗?我有一种感觉,由于 NSOperation 子类本身的错误,这条线不起作用?

有谁可以帮我离开这里吗?

非常感谢,

杰克

4

2 回答 2

2

问题是您如何设置操作。它被设置为非并发操作,因此它在单独的线程中执行 main 方法,然后完成。当委托被调用时,线程已经消失了。噗。您的问题是您没有保留线程。请参阅此处:如何在 NSOperation 中执行异步 NSURLConnection?

于 2012-05-18T16:32:04.147 回答
0

Joel 在start您应该调用该main方法以在主线程上启动的方法中是正确的,或者您需要保持调用方法 id 的线程处于活动状态。

于 2012-05-19T07:32:26.420 回答