2

我有两个UITableViewControllersA 和 B,当我单击 A 中的表格视图单元格时,这就是我想要做的事情:

  1. 准备通过从 A 设置 B 的一些变量来从 A 到 B。
  2. 执行从 A 到 B 的 segue。
  3. B 出现。
  4. 使用 显示“加载”活动指示器[MBProgressHUD][1]
  5. 在后台任务中,从 URL 检索数据。
  6. 如果 URL 请求发生错误(未收到数据或非 200 状态码),(a) 隐藏活动指示器,然后 (b) 显示带有错误消息的 UIAlertView
  7. 否则,(a)tableView用检索到的数据重新加载 B,然后 (b) 隐藏活动指示器

但是,这就是正在发生的事情,我不知道如何解决它:

  1. 单击 A 中的一个单元格后,B 从右侧滑入一个空白的 plain UITableViewMBProgressHUD 显示。
  2. 过了一会儿,tableView重新加载检索到的数据,MBProgressHUD出现非常短暂。
  3. MBProgressHUD立即消失。

执行后台任务的方式似乎没有错误。我的问题是,如何在MBProgressHUDB 视图控制器出现后立即显示活动指示器?(实际上,为什么它没有显示?)代码如下。

A的prepareForSegue

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    B *b = (B *)[segue destinationViewController];

    // Set some of B's variables here...
}

相关方法在B

- (void)viewDidAppear:(BOOL)animated {
    [self startOver];
}

- (void)startOver {
    [self displayLoadingAndDisableTableViewInteractions];
    [self retrieveListings];
    [self.tableView reloadData];
    [self hideLoadingAndEnableTableViewInteractions];
}

- (void)displayLoadingAndDisableTableViewInteractions {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.labelText = @"Loading";
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    self.tableView.userInteractionEnabled = NO;
}

- (void)hideLoadingAndEnableTableViewInteractions {
    [MBProgressHUD hideHUDForView:self.view animated:YES];
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    self.tableView.userInteractionEnabled = YES;
}

- (void)retrieveListings {
    __block NSArray *newSearchResults;

    // Perform synchronous URL request in another thread.
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        newSearchResults = [self fetchNewSearchResults];
    });

    // If nil was returned, there must have been some error--display a UIAlertView.
    if (newSearchResults == nil) {
        [[[UIAlertView alloc] initWithTitle:@"Oops!" message:@"An unknown error occurred. Try again later?" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
    } else {
        // Add the retrieved data to this UITableView's model. Then,
        [self.tableView reloadData];
    }
}

- (NSArray *)fetchNewSearchResults {
    // Assemble NSMutableArray called newSearchResults from NSURLConnection data.
    // Return nil if an error or a non-200 response code occurred.
    return newSearchResults;
}
4

3 回答 3

0

我认为您必须[self hideLoadingAndEnableTableViewInteractions];newSearchResults = [self fetchNewSearchResults];您在另一个线程中检索数据-startOver后调用,这意味着在调用后将继续执行[self retrieveListings];并立即隐藏 HUD。此外,因为您正在更新显示,您必须确保您在主线程上执行此操作。查看示例

dispatch_async(dispatch_get_main_queue(), ^{
            //update UI here
        });
于 2013-07-24T04:07:12.943 回答
0

出现时B,它显示一个普通的和空的,但即使任务确实在后台开始,UITableView它也不显示(然而,在此之前调用显示)。因此,我的解决方案是显示in ,它位于.MBProgressHUDMBProgressHUDMBProgressHUDviewDidLoadviewWillAppear

- (void)viewDidLoad {
    // ...
    [self displayLoadingAndDisableUI];
}

我在 .h 中设置了两个额外的布尔属性B,称为 .hshouldStartOverUponAppearing中的一个,在 .m 中的类扩展中设置了一个,称为isLoadingAndDisabledUI。在startOver中,我添加了以下几行:

- (void)startOver {
    if (!self.isLoadingAndDisabledUI) {
        [self displayLoadingAndDisabledUI];
    }
}

检查已完成,因此当它已经从显示时startOver不会显示另一个。那是因为我有第三个视图控制器,称为,它可能会调用's ,但不需要调用只是为了显示.MBProgressHUDviewDidLoadCBstartOverviewDidLoadMBProgressHUD

另外,这就是我定义的方式viewDidAppear

- (void)viewDidAppear:(BOOL)animated {
    if (self.shouldStartOverUponAppearing) {
        [self startOver];
        self.shouldStartOverUponAppearing = NO;
    }
}

这样,只有在从 A出现startOver时才会调用。如果通过按“Back”出现,它将什么也不做,只显示那里的旧数据。BBC

我认为这个解决方案远非优雅,但它有效。我想我只会在单独的 SO 问题中要求更好的方法。

于 2013-07-24T07:11:14.080 回答
0

我对 MBProgressHUD 使用了一种常用方法。

  1. AppDelegate.h中的#import "MBProgressHUD.h"也遵循以下方法。

    - (MBProgressHUD *)showGlobalProgressHUDWithTitle:(NSString *)title;
    - (void)dismissGlobalHUD;
    
  2. 在 AppDelegate.m 添加以下方法。

    - (MBProgressHUD *)showGlobalProgressHUDWithTitle:(NSString *)title {
       [MBProgressHUD hideAllHUDsForView:self.window animated:YES];
       MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.window animated:YES];
       hud.labelText = title;
       return hud;
    }
    
    - (void)dismissGlobalHUD {
      [MBProgressHUD hideHUDForView:self.window animated:YES];
    }
    
  3. 如何使用?

    AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication]delegate];
    //Show Indicator
    [appDel showGlobalProgressHUDWithTitle:@"Loading..."];
    //Hide Indicator
    [appDel dismissGlobalHUD];
    

希望这可以帮助。

于 2013-07-24T10:15:37.767 回答