当应用iOS GCD线程时,解析xml会停止工作

时间:2013-10-18 21:18:27

标签: ios xml grand-central-dispatch

我正在开发一个应用程序,用户使用Web服务将数据发送到中央数据库。 Web服务从中央数据库发回带有主键的XML文件,以便使用此主键更新应用程序上的本地数据库。当我不使用GCD时,一切都很完美。一旦我介绍了线程,我似乎没有得到解析的XML文件。似乎代码将XML发送到Web服务,但之后没有任何事情发生。我实现线程的方式有问题吗?这是代码示例:

-(void) viewDidLoad
{

dispatch_queue_t saveCentralDB = dispatch_queue_create("Writing Database", NULL);

        dispatch_async(saveCentralDB, ^ {


            NSLog(@"Created NEW THREAD to send info to CENTRAL DB");


           NSString *soapMsg = [NSString stringWithFormat:
                                     @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                                     "<soap12:Envelope "
                                     "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
                                     "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
                                     "xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">"
                                     "<soap12:Body>"
                                     "<InsertPurchase xmlns=\"http://tempuri.org/\">"


                                     "<RequestObject xsi:type = \"SpazaPurchaseRequest\">"

                                     "<PurchaseID>%@</PurchaseID>"
                                     "<RemoteSpazaPurchaseID>%@</RemoteSpazaPurchaseID>"
                                     "<UserID>%d</UserID>"

                                     "<RetailerID>%@</RetailerID>"
                                     "<ItemID>%@</ItemID>"
                                     "<CostPrice>%@</CostPrice>"
                                     "<Longitude>%@</Longitude>"
                                     "<Latitude>%@</Latitude>"
                                     "<DatePurchased>%@</DatePurchased>"
                                     "<Barcode>%@</Barcode>"
                                     "<BasketID>%@</BasketID>"
                                     "</RequestObject>"

                                     "</InsertPurchase>"
                                     "</soap12:Body>"
                                     "</soap12:Envelope>",@"0",pklPurchaseID1,fklUserID,fklRetailerID1,fklItemID1, lCostPrice1, sLongitude1, sLatitude1,dtPurchase1,sBarcode1,fklBasketID1];



                //---print of the XML to examine---
                NSLog(@"%@", soapMsg);

                NSURL *url = [NSURL URLWithString:@"http://www.myapp.com/purchases/ProviderWS.asmx?op=InsertPurchase"];




                NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
                NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMsg length]];


                [req addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
                [req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
                [req setHTTPMethod:@"POST"];
                [req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];

                conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
                if (conn)
                {
                    webData = [NSMutableData data];

                }


       });

}

然后,我实现了以下方法来处理来自Web服务的响应。

/************************Processing the feedback XML returned by webservice*****************/

-(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];




    //---prints the XML received---
    NSLog(@"%@", theXML);


    xmlParser = [[NSXMLParser alloc] initWithData: webData];
    [xmlParser setDelegate: self];
    [xmlParser setShouldResolveExternalEntities: YES];
    [xmlParser parse];

}

然后实现正常的委托方法:

- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    NSLog(@"XML Parsing Method: didStartElement");

    //This is the first node that we search for. The information we want is contained within this node.
    if ([elementname isEqualToString:@"ResponseMessage"])
    {
        currentCentralDBPurchase = [parsingCentralDBPurchaseXML alloc];

        //Flag to indicate that we are within the ResponseMessage node/tag.
        isStatus = YES;
    }

}



- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    NSLog(@"XML Parsing Method: foundCharacters");

    currentNodeContent = (NSMutableString *) [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}



- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if (isStatus)
    {
        if ([elementname isEqualToString:@"PurchaseID"])
        {
            currentCentralDBPurchase.centralPurchaseID = currentNodeContent;
        }


        if ([elementname isEqualToString:@"RemotePurchaseID"])
        {
            currentCentralDBPurchase.localPurchaseID = currentNodeContent;
        }
    }

    if ([elementname isEqualToString:@"ResponseMessage"])
    {
        //Update local database with the PurchaseID from the central database. This is how we will identify records that must still be sent to the central database.


        //Now update the local database with purchases that have been sent to central database

        // Get the DBAccess object;
        DBAccess *dbAccess = [[DBAccess alloc] init];



        [dbAccess UpdateCentralPurchaseID: [currentCentralDBPurchase.localPurchaseID integerValue] :[currentCentralDBPurchase.centralPurchaseID integerValue] ];


        // Close the database because we are finished with it
        [dbAccess closeDatabase];

        currentCentralDBPurchase = nil;

        //Clear the currentNodeContent node so we are ready to process the next one.
        currentNodeContent = nil;


    }
}

1 个答案:

答案 0 :(得分:1)

NSURLConnection initWithRequest:在这种情况下应该在主线程上调用。

dispatch_async(dispatch_get_main_queue(), ^{
    conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
    if (conn)
    {
        webData = [NSMutableData data];
    }
});

它依赖于RunLoop,Runloop会自动处理主线程。你可以在另一个线程上调用initWithRequest但是你应该在线程上执行RunLoop。但是在调度队列上有点困难,因此使用主队列对这种情况很有帮助。