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 では大文字と小文字が区別されるため、ここには 2 つの MBProgressHUD インスタンスがあります。

  • HUDビューに追加するよりも、で作成しますが[[MBProgressHUD alloc] initWithView:self.view];、表示に失敗します(最初は非表示になっています)
  • hudあなたが作成し、ビューに追加し、便利なコンストラクターですぐに表示します[MBProgressHUD showHUDAddedTo:self.view animated:YES];

これは本質的に、HUDがコード全体で非表示になり、設定したプロパティの変更は表示されず (処理中およびダウンロード中)、hudは表示され、設定したテキストのみが表示される (Connecting1) ことを意味します。

コードに追加のエラーがあり、バックグラウンド スレッドでビュー (hud MBProgressHUD インスタンス) を作成する必要があります。一般的な経験則は、メイン スレッドでのみビューのみを変更することです。hud のテキスト (およびその他のプロパティ) の設定は、ここで注目すべき例外の 1 つです。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 に答える