UIViewController动画停止工作

21

我的应用在iOS6上运行良好,但在某个我因为NDA原因不能透露名称的未来版本的iOS中,所有UIViewController过渡动画都停止工作,新视图就立即弹出。我不确定这个未具体说明的iOS未来版本是否是原因,因为我也曾经看到这种情况在iOS6上偶尔出现。

有时动画会在一段时间内开始工作,然后很快停止,这使我认为这可能是某种内存警告问题,但我的应用程序最多只使用相当合理的约125MB的RAM。有人能提供任何建议或要调查的事项吗?


这里需要更多的信息。你正在进行什么样的动画以及如何实现?你能否发布一些相关的代码?否则,你可能会在苹果开发者论坛上获得更多帮助。 - Bob Vork
我正在进行绝对正常的[self.navigationController pushViewController:viewController animated:YES] - 样式的视图控制器转换。不幸的是,根据我的经验,苹果开发者论坛相比于SO来说有点荒芜,但我也在那里开了一个帖子。 - Nick Locking
你完全没有使用自定义的UIViewController子类吗?只是库存部件?我从来没有听说过动画因为内存压力而停止;那似乎不太可能。 - Jeff
它们是子类,但完全标准的子类。据我所知,我绝对没有做任何奇怪的事情。它们有视图,我正在正常使用它们。 - Nick Locking
1
如果同一代码库存在于iOS 6中,并且您偶尔也在iOS 6中遇到它,为什么不将其发布进行审查呢? - Nirav Bhatt
显示剩余5条评论
4个回答

40
所述行为一直存在:如果您在后台线程上工作,然后调用UIKit方法,则更新往往会以奇怪的方式延迟。因此,您应始终在主队列上使用dispatch_async来更新UI。
这些错误很难捕获,因为它们不总是可预测的。为了捕获它们,我构建了一个方法,可以替换一些UIKit方法来检查它们是否在主线程上调用。这允许您在符号断点上停止,无论何时您忘记将任务派发回主队列。
链接:https://github.com/Cocoanetics/DTFoundation/blob/develop/Core/Source/iOS/Debug/UIView%2BDTDebug.m

那段代码就是我找到后台线程相关内容的方式。 - Nick Locking
从iHunter的源代码中,你需要DTObjectBlockExecutor、NSObject+DTRuntime和UIView+DTDebug来交换视图方法并捕获问题。 - Nick Locking
将代码导入项目有点麻烦(因为依赖项和Cocoapods不完整),但一旦设置断点,你会在几秒钟内找到错误的代码行。谢谢! - BastiBen
我该如何在我的项目中使用UIView_DTDebug类?我已经从源代码中添加了DTDebug、DTObjectBlockerExecutor、NSObject和UIVew类。但是我遇到了错误:无法找到UIView的接口声明等等... - Awais Tariq
非常感谢提供的链接!它帮助我找到了在后台线程中调用的 UI 函数。 - D6mi
@Cocoanetics 我该如何在我正在构建的Swift框架中使用这段代码?我已经将必要的文件放入了我的框架中,并在那里添加了一个桥接头文件。然后,我的框架被用于一个用Obj-C编写的示例项目中。即使动画停止工作,methodCalledNotFromMainThread也没有被调用。 - FateNuller

15

以下是苹果开发者论坛上关于此问题的一个不错的解决方案:

按照以下步骤操作:

[UIView setAnimationsEnabled:YES] 

动画又开始工作了。我怀疑这要么是iOS7的一个bug,要么是我的代码中有一个动画或UIViewController启动正在发生在后台线程上,导致动画停止。可能与未来版本的iOS无关。


顺便提一下,在我们的应用程序中,视图动画似乎工作正常。另外,我已经添加了一个问题。我认为这是一个可以的问题。 - ort11
1
你为什么要发表回答?而且还是两个回答?请在编辑后将其放入问题中... - Fahim Parkar

0
你所需要做的就是在从API接收响应时抓住主队列来更新UI。iOS默认使用主队列来更新UI,但这并不是100%有效的。因此,你必须确保UI只在主线程上更新,方法如下:
DispatchQueue.main.async{
  //UI related code eg: 
  self.label.text = "abc" 
  self.button.setTitle("xyz",.normal)
  self.tableView.reloadData()
}

如果您没有捕获主线程动画可能会无法正常工作。 但是,如果您使用主线程动画将绝对有效。

在 API 响应上更新 UI 的正确代码:

Alamofire.getApiCall(paramaters: parameters, completion:{
  response in 
  // UI related code.
  DispatchQueue.main.async{
    self.label.text = "abc" 
    self.button.setTitle("xyz",.normal)
    self.tableView.reloadData()
  }
})

不正确的代码可能导致动画停止,并导致奇怪的崩溃:

  Alamofire.getApiCall(paramaters: parameters, completion:{
  response in 
  // UI related code.
    self.label.text = "abc" 
    self.button.setTitle("xyz",.normal)
    self.tableView.reloadData()
})

0
这个问题似乎是由在后台线程中执行UIKit操作引起的。我有一个预渲染缓存,其中包含将复杂的UIView渲染为UIImage以缓存输出的NSOperations。这在iOS6中似乎运行良好,但可能有些超出了界限。我需要用一些东西来替换这个功能,它可以将图像和文本渲染到图形缓冲区,而不是完全使用UIView和UILabel。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接