UIAlertView 开始显示,屏幕变暗,但直到为时已晚才弹出!

Posted

技术标签:

【中文标题】UIAlertView 开始显示,屏幕变暗,但直到为时已晚才弹出!【英文标题】:UIAlertView starts to show, screen dims, but it doesn't pop up until it's too late! 【发布时间】:2011-03-03 19:02:23 【问题描述】:

我有一个按钮,按下该按钮时会调用从一系列 URL 加载信息(大约 5 秒加载时间)。在实际拨打这些电话之前,我想添加一个“加载”警报。当我使用 UIAlertView 时,屏幕会变暗,就像它即将弹出一样,但直到数据加载后才会出现 - 为时已晚!我不知道发生了什么,就像我为加载数据所做的调用立即优先于显示新视图,即使它们是在调用添加新视图(或显示警报)之后立即进行的. 这是代码的摘要版本:

-(void) refresh
   UIAlertView *av = ...
   [av show]; //this should pop up before dat begins to load
   [myDataSource loadData]; //this contains a series of [NSData initWithURL] calls
   [self.tableView reloadData];
   //here I would hide the AlertView, but if I do I see it for just s split second
   //when the tableView has already reloaded
 

提前感谢您的任何见解!

***编辑 对于使用 performSelectorInBackground 的任何人,请注意创建有效的线程程序所增加的复杂性。例如,泄漏可能会在新线程没有自动释放池时出现 - 您必须添加一个,等等。

【问题讨论】:

如果我理解正确,您实际上是在阻止调用线程安排要显示的警报,并在安排视图时重新加载表视图项。因此,当方法返回时,表视图已经知道要填充的所有行。你能分别和异步地做这两件事吗?就像,使用异步 performSelector:afterDelay: 或 dispatch_after() 调用,首先显示警报然后重新加载数据,分别?这可能会有所帮助。 【参考方案1】:

当您尝试从 Internet 检索数据时(我猜您正在使用 [NSString stringWithContentsOfURL: ...] 之类的东西),主线程正在等待这些数据,因此应用程序无法重绘界面。 您可以尝试使用:

[mySourceData performSelectorInBackground:@selector(loadData) withObject:nil];

如果您在对 NSManagedObjectContext 进行任何操作之前使用 coredata 锁定它并在完成后解锁它,请小心。

【讨论】:

好的,现在我明白发生了什么,谢谢!虽然我过度简化了我的代码,但 loadData 方法实际上返回了一个 NSArray ,并且从我发现的内容中,如果该方法返回一个值,我就不能使用 performSelectorInBackground 。我在想我可以更改 loadData 以便它接收一个可以是调用者的参数,然后当它完成时它可以通知调用者说它已经完成。那将需要设置一个协议,调用 loadData 的类将是委托,对吗?我还没有做过很多这样的事情...... 正确。同样正如@Bogatyr 建议的那样,您可以将 NSOperation 与 NSOperationQueue 一起使用。 好的,一切都解决了!我设置了我的协议,当加载数据时,我的“加载”视图被删除就好了。所以基本上我现在调用获取数据的方法是 (void)loadData:(id)caller.【参考方案2】:

如果你有一堆操作要执行,除了 performSelectorInBackground: 就像 cescofry 写的那样,你可以使用 NSOperation 和 NSOperationQueue。

【讨论】:

感谢您的回复,我以后可能需要在更密集的任务中使用这些。 关于 NSOperationQueue 真正酷的事情之一是您可以轻松地调高/调低并发性,甚至可以根据需要在代码中动态地进行拨号。【参考方案3】:

无论如何,您可能不想要 UIAlertView。看看MBProgressHUD on GitHub。

【讨论】:

我实际上也尝试过使用它(它更好),但基本上发生了同样的事情 - 直到重新加载表格后视图才显示!如果我找出导致这两件事的原因,我可能最终会使用 MBProgressHUD,但现在屏幕变暗但警报没有显示的事实可能更能说明问题。 如果-loadData 是一个冗长的操作,您应该在后台线程中执行它,以免阻塞用户界面。您正在为 4.0+ 构建吗?如果是这样,我会认真建议利用 GCD 并将 -loadData 包装在 dispatch_async() 调用中。额外的好处是,当双核 ios 设备成为标准时,您的代码实际上将在一夜之间实现两倍的速度。

以上是关于UIAlertView 开始显示,屏幕变暗,但直到为时已晚才弹出!的主要内容,如果未能解决你的问题,请参考以下文章

如何创建自定义 UIAlertView

当我在 Xamarin 应用程序中调用 DisplayAlert 时,屏幕变暗但不显示警报

如何更改 UIAlertView 按钮的宽度?

UIAlertView 滚动问题

我可以移动 UIAlertView 吗?

在 OS X 上防止屏幕变暗和显示睡眠