【问题标题】:UIActivityIndicatorView doesn't appear anymore during web service callUIActivityIndi​​catorView 在 Web 服务调用期间不再出现
【发布时间】:2014-06-30 02:59:30
【问题描述】:

昨天我在我的 iOS 应用程序中添加了一个UIActivityIndicatorView,一切都很好,现在我正在尝试运行同一个应用程序,但 UIActivityIndicatorView 不再显示,agenda 视图(调用 Web 服务) 需要很长时间(比昨天更长)才会出现,而且通常根本不会出现。请问我该如何解决这个问题?这是我的代码:

- (IBAction)agenda:(id)sender {

    UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    spinner.center = CGPointMake(160, 240);
    spinner.hidesWhenStopped = YES;
    [self.view addSubview:spinner];
    [spinner startAnimating];
    // how we stop refresh from freezing the main UI thread
    dispatch_queue_t downloadQueue = dispatch_queue_create("downloader", NULL);
    dispatch_async(downloadQueue, ^{

        // do our long running process here
        // [NSThread sleepForTimeInterval:10];
        AgendaViewController *agenda = [[ AgendaViewController alloc] initWithNibName:nil bundle:nil];

        // do any UI stuff on the main UI thread
        dispatch_async(dispatch_get_main_queue(), ^{

            [spinner stopAnimating];
            [self.navigationController pushViewController:agenda animated:YES];           
        });

    });
    dispatch_release(downloadQueue);

}

【问题讨论】:

  • 我觉得这段代码没问题。我建议注释掉queue 代码并检查微调器是否出现(不要stopAnimating)。想到的第一个罪魁祸首是您没有显示的“长时间运行的进程”代码。
  • 当我注释 queue 代码时,即使在队列代码未注释时使用 [NSThread sleepForTimeInterval:10];,微调器也会显示,但当我添加此代码时它不会出现:AgendaViewController *agenda = [[ AgendaViewController alloc] initWithNibName:nil bundle:nil]; 似乎这行引起的问题是我要在“长时间运行的过程”中添加的代码有什么建议吗?
  • 尝试使用 dispatch_async(dispatch_get_main_queue() 块在主线程上添加微调器子视图。
  • 好的,试着给你的AgendaViewController一个标识符,然后像这样实例化你的对象。我假设您使用的是storyboards。这是example
  • 不,我使用的是 xib 文件

标签: ios objective-c uiactivityindicatorview


【解决方案1】:

问题必须与您实例化 议程 VC 的方式有关。如果您使用的是xib 文件,那么您需要将xib 的名称传递给您的initWithNibName。使用nil 参数调用initWithNibName: 与仅调用init 相同。它将直接从类 definition 创建一个对象,但它不会包含您在 xib 文件中自定义创建的任何内容。

我相信,当您取消注释“您认为”的 sleepForTimeInterval: 行时,它会起作用,因为它有足够的时间在推动 空白 议程 VC 之前显示微调器。

注意:initWithNibName:nil 参数一起使用的唯一方法(我仍然认为您应该只调用init),即xib 文件以您的VC 命名。更多信息here

更新

根据对此答案的评论,您的长期运行进程不在async 代码内,而是在AgendaViewController 内的viewDidLoad: 方法中。因此,一种解决方案是:

  1. action 中完全删除async 代码,并仅将其替换为AgendaViewControllerinit/push 逻辑。
  2. 在您的AgendaViewControllerviewDidLoad: 中添加/启动UIActivityIndicatorView
  3. 调用 mySQL 数据库(实际的“长期运行的进程”)。
  4. 当您收到数据时停止 spinner/activityIndi​​cator

我不知道您是如何实现 mySQL 调用(Web 服务/api)的,但它应该提供在完成时调用的 blockprotocol 方法.这就是您需要添加逻辑以停止 spinner 的地方。

【讨论】:

  • 谢谢 Callistino,我将 nil 更改为 xib 文件的名称,它在第一次测试中运行良好,然后我尝试再次运行应用程序,同样的问题又出现了,@987654348 @disappeared,几秒钟后agendaview 正常出现,与问题中的代码相同,昨天工作正常,但现在不行了,不知道为什么!
  • 那么您需要向我们展示您的“长期运行”流程是什么。我怀疑您在尝试实例化agenda VC 之前正在执行一些未完成的async 操作。如果是这种情况,您需要使用async 操作return/block 来实例化您的agenda VC。那么,你就根本不需要GCD了。
  • 我的长期运行过程是声明agendaview,然后从dispatch_async(dispatch_get_main_queue(), ^{block 中推送它(agendacalls 来自mysqldatabase 的数据在它的viewdidloadmethod 这是为什么加载和显示其内容需要时间)所以“长时间运行的进程”只包含以下代码:AgendaViewController *agenda = [[ AgendaViewController alloc] initWithNibName:@"AgendaViewController" bundle:nil]; agenda.lat = lat; agenda.longt = longt; agenda.agendaBackOffice = @"0"; agenda.agendaStatut= @""; agenda.userId = @"";
  • 这就是问题所在,您在 async 进程上初始化您的 VC,但 实际长时间运行的进程直到viewDidLoad:VC 被推到navigationController 之前不会发生。换句话说,您的视图会在数据加载之前和activityIndicatorView 停止之后显示(推送)。
  • 感谢您的回复,但我该如何解决这个问题?
【解决方案2】:

你的代码对我来说很奇怪。

如果AgendaViewControllerUIViewController,那么它应该在主线程上被触及。 因此,我会将用于从服务中检索数据的代码与与 UIViewController 相关的代码分开。

我将修改代码如下。这是一个可能的解决方案。

// spinner could become a strong property int the presenter controller
self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.spinner.center = CGPointMake(160, 240);
self.spinner.hidesWhenStopped = YES;
[self.view addSubview:self.spinner];
[self.spinner startAnimating];

__weak typeof(self) weakSelf = self;

// moved the dispatch_queue into an instance variable or property but do not forget to release
dispatch_async(downloadQueue, ^{

    // call the service here to retrieve serverData

    // do any UI stuff on the main UI thread
    dispatch_async(dispatch_get_main_queue(), ^{

        typeof(self) strongSelf = weakSelf;
        if(strongSelf) {
            AgendaViewController *agenda = [[ AgendaViewController alloc] initWithNibName:nil bundle:nil];
            agenda.serverData = serverData;
            [strongSelf.navigationController pushViewController:agenda animated:YES];
            [strongSelf.spinner stopAnimating];     
        }    
    });

});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多