2013-10-18 26 views
1

我正在處理用戶使用Web服務將數據發送到中央數據庫的應用程序。 Web服務使用中央數據庫中的主鍵發回XML文件,以便使用此主鍵更新應用程序上的本地數據庫。當我不使用GCD時,一切正常。只要我引入線程,我似乎沒有得到XML文件解析。看起來代碼將XML發送到Web服務,但此後沒有任何反應。我執行線程的方式有什麼問題嗎?下面是代碼示例:當應用iOS GCD線程時,xml解析停止工作

-(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 Service的響應。

/************************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

NSURLConnection的initWithRequest:應該在這種情況下,主線程中調用。

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

它依靠RunLoop和Runloop自動工作在主線程上。你可以在另一個線程上調用initWithRequest,但是你應該在線程上執行RunLoop。然而,在調度隊列上有點困難,因此使用主隊列對於情況很有幫助。

+0

它完美的作品!!!!!!你拯救了我的生命@Kazuki ....你是我的英雄。太感謝了! – BDR