0

在我看来,我试图显示一些与天气相关的信息。我用

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    Make NSURL and other related things
    Send NSURLRequest
    Set 2 UILabels to data
    NSLog(Show data retrieved)
});

出于某种原因,我在 uilabel 更改为新文本之前大约 15-45 秒看到了 NSLog 行。我对 Obj-C 相当陌生,我的很多代码都来自使用教程,所以我对 dispatch_async 方法没有最了解。任何想法或建议将不胜感激。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURLResponse *response = nil;
        NSError *error = nil;
        NSData *respData = nil;
        NSURLRequest *forecastRequest = [NSURLRequest requestWithURL:currentForecastUrl];
        respData = [NSURLConnection sendSynchronousRequest:forecastRequest returningResponse:&response error:&error];
        [_responseData appendData:respData];
        NSLog(@"Response: %@", response);
        NSLog(@"Error: %@", error);
        id JSON = [_responseData yajl_JSON];
        currentForecast = [[NSArray alloc]initWithObjects:[JSON objectForKey:@"temperature"],[JSON objectForKey:@"feelsLike"],nil];

        [_temperatureLabel setText:[NSString stringWithFormat:@"%@",[JSON objectForKey:@"temperature"]]];
        [_tempDescriptionLabel setText:[NSString stringWithFormat:@"%@",[JSON objectForKey:@"desc"]]];
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:2.0];
        [_tempDescriptionLabel setAlpha:1];
        [_temperatureLabel setAlpha:1];
        [UIView commitAnimations];
        NSLog(@"Done");

        NSLog(@"JSON: %@", [JSON yajl_JSONStringWithOptions:YAJLGenOptionsBeautify indentString:@"  "]);
    });
4

4 回答 4

2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

用于创建后台线程,但用户界面应在主线程中更新

像这样:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     //do stuff in background

     dispatch_async(dispatch_get_main_queue(), ^{

         // Update your UI
     });

});
于 2014-01-31T15:27:35.100 回答
1

所有“使用主队列”的答案都很好。但请注意 NSURLConnection 为您完成了所有这些工作。

[NSURLConnection sendAsynchronousRequest:request 
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

    // this happens on the main thread because we passed mainQueue
}];

编辑:这是你的代码,除了更小和现代语法。它应该做完全相同的工作。为了好玩,将其剪切并粘贴进去。

// it assumes the following variables in scope

NSURL *currentForecastUrl;
__block NSArray *currentForecast;
UILabel *_temperatureLabel, *_tempDescriptionLabel;

// start counting lines here
NSURLRequest *forecastRequest = [NSURLRequest requestWithURL:currentForecastUrl];
[NSURLConnection sendAsynchronousRequest:forecastRequest queue:[NSOperationQueue mainQueue]
    completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

    // I cheated a little on lines, because we really ought to check errors
    // in here.
    NSError *parseError;  // use native JSON parser
    id parse = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&parseError];
    currentForecast = @[parse[@"temperature"], parse[@"feelsLike"]];  // note the array and dictionary literal syntax

    _temperatureLabel.text = parse[@"temperature"];   // if these are ivars, I reccomend using self.temperatureLabel, not _temp...
    _tempDescriptionLabel.text = parse[@"desc"];
    [UIView animateWithDuration:2.0 animations:^{     // use UIView animation block
        _temperatureLabel.alpha = 1.0;
        _tempDescriptionLabel.alpha = 1.0;
    }];
}];

删除代码对我来说是编程中最愉快的部分。最容易阅读、执行最快且不需要测试的代码行是不存在的代码行。

于 2014-01-31T15:33:23.450 回答
0

您的问题是因为您试图UILabel从主线程中更新 s 。我之前已经看到过这种确切的症状,在主线程之外更新 UI 元素仍然会更新它们,但是延迟很长。因此,只要您有一个以这种方式运行的 UI 元素,请检查以确保它在主线程上执行。

于 2014-01-31T15:25:51.873 回答
0

我很惊讶这段代码完全有效,因为您正在更新后台线程上的标签。您想按照以下方式做一些事情:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{
    //Make NSURL and other related things
    //Send NSURLRequest
    dispatch_async(dispatch_get_main_queue(), ^{
        // Set your UILabels
    });
});
于 2014-01-31T15:28:19.613 回答