gpt4 book ai didi

ios - 后台线程上的 NSURLConnection 委托(delegate)方法

转载 作者:可可西里 更新时间:2023-11-01 05:42:17 25 4
gpt4 key购买 nike

EDIT2 - 重写问题

我想在后台做一些网络服务通信。我正在使用 Sudzc作为 HTTPRequests 的处理程序,它的工作方式如下:

SudzcWS *service = [[SudzcWS alloc] init];
[service sendOrders:self withXML:@"my xml here" action:@selector(handleOrderSending:)];
[service release];

它向 web 服务发送一些 XML,响应(在这个中,一个 bool 值)在指定的选择器中处理:

- (void)handleOrderSending:(id)value
{
//some controls
if ([value boolValue] == YES)
{
//my stuff
}
}

当我尝试在我的 sendOrders:withXML:action: 方法上使用 Grand Central Dispatch 时,我注意到没有调用选择器。我相信这样做的原因是 NSURLConnection 委托(delegate)消息被发送到创建连接的线程 但是线程不会活那么久,它在方法完成时结束,杀死任何消息代表。

问候

编辑1[请求发送]方法:

- (void) send {
//dispatch_async(backgroundQueue, ^(void){
// If we don't have a handler, create a default one
if(handler == nil) {
handler = [[SoapHandler alloc] init];
}

// Make sure the network is available
if([SoapReachability connectedToNetwork] == NO) {
NSError* error = [NSError errorWithDomain:@"SudzC" code:400 userInfo:[NSDictionary dictionaryWithObject:@"The network is not available" forKey:NSLocalizedDescriptionKey]];
[self handleError: error];
}

// Make sure we can reach the host
if([SoapReachability hostAvailable:url.host] == NO) {
NSError* error = [NSError errorWithDomain:@"SudzC" code:410 userInfo:[NSDictionary dictionaryWithObject:@"The host is not available" forKey:NSLocalizedDescriptionKey]];
[self handleError: error];
}

// Output the URL if logging is enabled
if(logging) {
NSLog(@"Loading: %@", url.absoluteString);
}

// Create the request
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL: url];
if(soapAction != nil) {
[request addValue: soapAction forHTTPHeaderField: @"SOAPAction"];
}
if(postData != nil) {
[request setHTTPMethod: @"POST"];
[request addValue: @"text/xml; charset=utf-8" forHTTPHeaderField: @"Content-Type"];
[request setHTTPBody: [postData dataUsingEncoding: NSUTF8StringEncoding]];

if(self.logging) {
NSLog(@"%@", postData);
}
}


//dispatch_async(dispatch_get_main_queue(), ^(void){
// Create the connection
conn = [[NSURLConnection alloc] initWithRequest: request delegate: self];
if(conn) {
NSLog(@" POST DATA %@", receivedData);
receivedData = [[NSMutableData data] retain];
NSLog(@" POST DATA %@", receivedData);
} else {
// We will want to call the onerror method selector here...
if(self.handler != nil) {
NSError* error = [NSError errorWithDomain:@"SoapRequest" code:404 userInfo: [NSDictionary dictionaryWithObjectsAndKeys: @"Could not create connection", NSLocalizedDescriptionKey,nil]];
[self handleError: error];
}
}
//});


//finished = NO;

// while(!finished) {
//
// [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
//
// }

//});
}

注释掉的部分是我尝试过的各种东西。最后一部分有效,但我不确定这是否是一个好方法。在类的 NURLConnection 委托(delegate)方法中,会发生以下情况:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSError* error;
if(self.logging == YES) {
NSString* response = [[NSString alloc] initWithData: self.receivedData encoding: NSUTF8StringEncoding];
NSLog(@"%@", response);
[response release];
}

CXMLDocument* doc = [[CXMLDocument alloc] initWithData: self.receivedData options: 0 error: &error];
if(doc == nil) {
[self handleError:error];
return;
}

id output = nil;
SoapFault* fault = [SoapFault faultWithXMLDocument: doc];

if([fault hasFault]) {
if(self.action == nil) {
[self handleFault: fault];
} else {
if(self.handler != nil && [self.handler respondsToSelector: self.action]) {

[self.handler performSelector: self.action withObject: fault];


} else {
NSLog(@"SOAP Fault: %@", fault);
}
}
} else {
CXMLNode* element = [[Soap getNode: [doc rootElement] withName: @"Body"] childAtIndex:0];
if(deserializeTo == nil) {
output = [Soap deserialize:element];
} else {
if([deserializeTo respondsToSelector: @selector(initWithNode:)]) {
element = [element childAtIndex:0];
output = [deserializeTo initWithNode: element];
} else {
NSString* value = [[[element childAtIndex:0] childAtIndex:0] stringValue];
output = [Soap convert: value toType: deserializeTo];
}
}

if(self.action == nil) { self.action = @selector(onload:); }
if(self.handler != nil && [self.handler respondsToSelector: self.action]) {


[self.handler performSelector: self.action withObject: output];


} else if(self.defaultHandler != nil && [self.defaultHandler respondsToSelector:@selector(onload:)]) {
[self.defaultHandler onload:output];
}
}

[self.handler release];
[doc release];
[conn release];
conn = nil;
[self.receivedData release];
}

委托(delegate)无法发送消息,因为它所在的线程在 -(void)send 完成时终止。

最佳答案

sendOrders 的方法定义表明它已经被设计为以异步方式执行请求。你应该看看 sendOrders: withXML: action: 的实现查明情况是否如此。

如果没有看到您使用 GCD 或来自 SudzcWS 的代码的实现,很难说出了什么问题。尽管有前面的警告,但以下内容可能会有用。

看起来你可能会发布 SudzcWS *service在完成之前。

以下内容:

SudzcWS *service = [[SudzcWS alloc] init];
dispatch_async(aQueue, ^{
[sevice sendOrders:self withXML:xml action:@selector(handleOrderSending:)];
}
[service release];

除非 SudzcWS 保留自己,否则可能会失败。您异步分派(dispatch)您的 block ,它被放入队列中,然后继续执行该方法。 service在 block 执行之前或 service 期间被释放并被释放正在等待网络服务器的响应。

除非另有说明,否则调用选择器将在调用它的同一线程上执行该选择器。做类似的事情:

SudzcWS *service = [[SudzcWS alloc] init];
dispatch_async(aQueue, ^{
[sevice sendOrders:self withXML:xml action:@selector(handleOrderSending:)];
}


- (void)handleOrderSending:(id)value
{
//some controls
//your stuff
[service release];
}

应确保sendOrders:方法和 handleOrderSending:在队列 aQueue 上执行那service在执行选择器之前不会释放。

这将要求您保留指向 service 的指针这样handleOrderSending:可以释放它。您可能还想考虑简单地卡在单个 SudzcWS 实例上,而不是每次要使用它时都创建和释放一个实例,这应该会使您的内存管理更容易,并有助于保持对象图的紧凑。

关于ios - 后台线程上的 NSURLConnection 委托(delegate)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10249377/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com