2

HUD在处理线程和主线程上更改标签的最佳方法是什么?

[activitySpinner startAnimating];
    //[HUD setLabelText:@"Connecting"];
    //[HUD showUsingAnimation:YES];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
        hud.labelText = @"Connecting1";

        NSString *url = [NSString stringWithFormat:@"my URL", [dataObj.pListData objectForKey:@"API_BASE_URL"], userField.text, passwordField.text];
        NSLog(@"Login: %@",url);
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];

        NSError *error;        
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
        [HUD setLabelText:@"Processing"];
        dispatch_async(dispatch_get_main_queue(), ^{
            if ([json objectForKey:@"authToken"] != nil) {
                [HUD setLabelText:@"Logging In"];
                NSLog(@"Found authtoken %@", [json objectForKey:@"authToken"]);
                [dataObj setAuthToken:[json objectForKey:@"authToken"]];
                [dataObj setLocationId:[json objectForKey:@"c_id"]];

                [dataObj setStaffId:[[json objectForKey:@"staffOrRoomsId"] integerValue]];
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
                [HUD setLabelText:@"Downloading"];

                });

                [self getAllData];
                [self performSegueWithIdentifier:@"segueToRootController" sender:self];


            } else {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:[json objectForKey:@"friendlyErrors"] delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
                [alert show];
                alert = nil;
            }
            [MBProgressHUD hideHUDForView:self.view animated:YES];
        });


        [activitySpinner stopAnimating];
    });

我已经尝试了上述方法,因为如果我在主线程上运行标签更改,直到所有处理完成后它才会更改。

在我的viewWillAppear我设置

HUD = [[MBProgressHUD alloc] initWithView:self.view];
    [self.view addSubview:HUD];
    HUD.delegate = self;

它将显示正在连接,但不会显示正在处理或正在下载。

4

2 回答 2

1

由于 Objective-C 区分大小写,因此这里有两个 MBProgressHUD 实例:

  • HUD您使用 , 创建的[[MBProgressHUD alloc] initWithView:self.view];,而不是添加到视图中,但无法显示(最初是隐藏的)
  • hud您创建,添加到视图并立即使用便捷的构造函数显示[MBProgressHUD showHUDAddedTo:self.view animated:YES];

这实质上意味着它HUD在您的代码中是隐藏的,并且您对其设置的任何属性更改都不会显示(处理和下载),而hud可见并显示您在其上设置的唯一文本(连接 1)。

您的代码中还有一个错误,它涉及在后台线程中创建一个视图(hud MBProgressHUD 实例)。一般的经验法则是只在主线程中修改视图。在这里设置 hud 的文本(和其他一些属性)是一个值得注意的例外,因为 MBProgressHUD 在这里做了一些 KVO 技巧以确保您的线程安全。

另外您应该知道,即使您修复了上述错误,您也会遇到这样一种情况:您将文本设置为“登录”(或显示警报)并立即隐藏 HUD,这意味着该文本将仅非常短暂可见。下载完成后,您可能不想隐藏 HUD。activitySpinner 也有类似的问题。

总而言之,您可能会尝试这样的事情(从我的头顶写):

[activitySpinner startAnimating];
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = @"Connecting1";
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSString *url = [NSString stringWithFormat:@"my URL", [dataObj.pListData objectForKey:@"API_BASE_URL"], userField.text, passwordField.text];
    NSLog(@"Login: %@",url);
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];

    NSError *error;        
    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
    [hud setLabelText:@"Processing"];
    dispatch_async(dispatch_get_main_queue(), ^{
        if ([json objectForKey:@"authToken"] != nil) {
            [hud setLabelText:@"Logging In"];
            NSLog(@"Found authtoken %@", [json objectForKey:@"authToken"]);
            [dataObj setAuthToken:[json objectForKey:@"authToken"]];
            [dataObj setLocationId:[json objectForKey:@"c_id"]];

            [dataObj setStaffId:[[json objectForKey:@"staffOrRoomsId"] integerValue]];
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
                [HUD setLabelText:@"Downloading"];
                // Download synchronosly here? 
                dispatch_async(dispatch_get_main_queue(), ^{
                    [MBProgressHUD hideHUDForView:self.view animated:YES];
                    [activitySpinner stopAnimating];
                });
            });

            [self getAllData];
            [self performSegueWithIdentifier:@"segueToRootController" sender:self];
        } else {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:[json objectForKey:@"friendlyErrors"] delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
            [alert show];
            alert = nil;
            [MBProgressHUD hideHUDForView:self.view animated:YES];
            [activitySpinner stopAnimating];
        }
    });
});
于 2012-04-21T20:40:57.433 回答
0

实际上,在设备上对此进行测试后,我发现它确实显示正在处理和下载。它只是没有在模拟器中显示。我想因为它使用计算机处理器,所以它发生得如此之快。

于 2012-04-23T15:06:05.800 回答