我正在开发一个应用程序,用户使用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;
}
}
答案 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。但是在调度队列上有点困难,因此使用主队列对这种情况很有帮助。