NSURLConnection Async间歇性地返回null

时间:2013-06-11 20:49:44

标签: iphone ios objective-c asynchronous nsurlconnection

考虑到以下代码,我将我的应用程序从同步调用移动到异步调用以停止UI冻结。 - 除了一些小细节外,一切正常。

当它是同步调用时,它们总是返回一个值(即使花了很长时间(5或6秒)) 但是现在:

  1. ASync调用有时非常快,其他时间需要8或9秒(我也有光纤互联网)

  2. 他们提取的文本数据有时似乎没有返回,或者他们超时,因为myLabel文本最终设置为'NULL' - 我知道这不是我正在使用API​​的网站,因为它始终为Sync调用和浏览器返回一个值。

  3. 有什么想法吗? 谢谢!

    编辑:日志的错误响应是:响应: 错误:(null)

    [NSURLConnection sendAsynchronousRequest:requestGBP queue:operationQueue completionHandler: ^(NSURLResponse* response, NSData* data, NSError* error)
        {
            responseGBP = data;
            NSString *json_stringGBP = [[NSString alloc] initWithData:responseGBP encoding:NSASCIIStringEncoding];
            self.feedGBP = [parser objectWithString:json_stringGBP error:nil];
    
    
            NSString *GBP = [NSString stringWithFormat:@"Info Last: %@" feedGBP ObjectForKey:@"value"]];
    
            [myLabel setText:GBP];
    
    
        }];
    

    EDIIT ::我也在日志窗口看到“不应该到达这里”很多?!它不是我的NSLog代码的一部分!

2 个答案:

答案 0 :(得分:1)

取决于您的队列,您如何以及在哪里推介operationQueue? 更重要的是,何时调用异步连接?

如果你是在动画的UIView中调用它们,比如tableView或scrollView,那么当table / scrollView滚动时,队列将以这种方式运行。

为了能够调试更多信息,您还需要NSLog(@"Response: %@\r\nError: %@", response, error)

但是形成我的经验我非常怀疑第一种情况是造成这种情况,你也可以尝试使用默认队列而不是你自己的队列,这样的事情(不推荐,但可能有助于调试):

[NSURLConnection sendAsynchronousRequest:requestGBP queue:[NSOperationQueue currentQueue] completionHandler: ^(NSURLResponse* response, NSData* data, NSError* error)

编辑1:添加简单的代码更改以使事情变得更容易

正如我所怀疑的那样,你在动画视图中触发调用会导致延迟,我会做的是将aSync连接恢复为同步连接,而是在后台线程上调用它们。

以下是事物的外观(未经测试的代码,可能包含错误或需要进行一些调整)

将您的呼叫转移到新方法,称之为performRequest:(URLRequest *)req;

- (无效)performRequest:(的URLRequest *)aRequest {

NSError *err;
NSURLResponse *response;
NSData *returnData;

returnData = [NSURLConnection sendSynchronousRequest:aRequest
                                   returningResponse:&response
                                               error:&err];

if(!err && nil != returnData){
   //Perform action with your data here
   //IMPORTANT: if you have to use the data to update the UI again, then you
   //Must perform that on the main thread, this code will always be called in the
   //background thread, to do that simply do a call using GCD on the main Queue, like this

    dispatch_async(dispatch_get_main_queue(), ^{
        //Do only your UI updates here
    });

}else{
   NSLog(@"An error has occurred: %@", err);
}

}

无论何时您需要执行网络请求,(来自您的动画内等) 你只需在后台线程中调用它,就像这样

//Place this right after you create your requestGBP request
[self performSelectorInBackground:@selector(performRequest:) withObject:requestGBP];

以这种方式试一试,让我知道为你做的事情!

答案 1 :(得分:1)

检查错误是否 nil ,在这种情况下打印它,它将帮助您理解问题。我还会在这里评论有关编码的评论(通过CodaFi),以及关于更新主线程上的UI(这不是问题的原因,但后来可能会变得讨厌):

[NSURLConnection sendAsynchronousRequest:requestGBP queue:operationQueue completionHandler: ^(NSURLResponse* response, NSData* data, NSError* error)
{
    if(error)
    {
        NSLog(@"%@",error);
    }
    else
    {
        // Get the right string encoding:
        NSStringEncoding encoding= NSASCIIStringEncoding; // This in case the page will
                                                          // not return any encoding.
        if(response.textEncodingName)
        {
            encoding= CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef) text.encodingName));
            // A bit messy right? Don't get lost, read these functions on the 
            // documentation: http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFStringRef/Reference/reference.html
        }
        responseGBP = data;
        NSString *json_stringGBP = [[NSString alloc] initWithData:responseGBP encoding: encoding];
        self.feedGBP = [parser objectWithString:json_stringGBP error:nil];
        NSString *GBP = [NSString stringWithFormat:@"Info Last: %@" feedGBP ObjectForKey:@"value"]];
        // Update the UI on main thread:
        [myLabel performSelectorOnMainThread: @selector(setText:) withObject: GBP waitUntilDone: NO];
    }
}];