1

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

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

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

  2. 他们获取的文本数据有时似乎没有返回或超时,因为 myLabel 文本最终设置为“NULL” - 我知道这不是我使用 API 的网站,因为它总是返回 Sync 的值调用和在浏览器中。

有任何想法吗?谢谢!

编辑:来自日志的错误响应是:响应:错误:(空)

[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 代码的一部分!

4

2 回答 2

1

检查error是否不是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];
    }
}];
于 2013-06-11T21:37:43.290 回答
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 连接恢复为 Sync 连接,而是在后台线程上调用它们。

事情应该是这样的(未经测试的代码,可能包含错误或需要一些调整)

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

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

以这种方式试一试,让我知道你的情况如何!

于 2013-06-11T21:15:02.340 回答