设置UILabel文本的时间比预期的iOS7要长

时间:2014-01-31 15:21:14

标签: ios uilabel dispatch-async

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

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 个答案:

答案 0 :(得分: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
     });

});

答案 1 :(得分: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;
    }];
}];

为我删除代码是编程中最令人愉快的部分。最容易阅读的代码行,执行速度最快,不需要测试的是不存在的行。

答案 2 :(得分:0)

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

答案 3 :(得分: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
    });
});