当 segue 是模式时,performSegueWithIdentifier 非常慢
performSegueWithIdentifier very slow when segue is modal
我有一个简单的 table 视图,我在其中处理 table 视图上的 select 操作。此操作遵循一个 segue。
如果 segue 是 push
segue,下一个视图会立即显示。
如果 segue 是 modal
segue,下一个视图要么:
- 显示需要 6 秒左右
- 如果我再次点击(第二次点击)会立即显示
我试着四处寻找一些想法,但 none 似乎适用于我的情况。特别是:
- 我正在主 UI 线程上执行 segue
- 我的看法很简单(所以
viewDidLoad
没有问题)。再加上它在 segue 为 push
时几乎瞬间显示的事实表明加载目标视图没有问题
- 我尝试将
nil
传递给 sender
;同样的效果。
有人对此有什么想法吗?
相信我,试试这个。我 运行 遇到过这个问题几次。
在Swift 2:
dispatch_async(dispatch_get_main_queue(),{
self.performSegue(withIdentifier:mysegueIdentifier,sender: self)
})
或 Swift 3:
DispatchQueue.main.async {
self.performSegue(withIdentifier: mysegueIdentifier,sender: self)
}
正如所讨论的 here and here。
接受的解决方案对我有用。 Swift 2.0 的代码更新如下:
dispatch_async(dispatch_get_main_queue(),{
self.performSegueWithIdentifier(mysegueIdentifier, sender:self)
})
希望对您有所帮助,您可以在 Swift 中以编程方式创建模式转换:
let myStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let modalViewController = myStoryboard.instantiateViewControllerWithIdentifier("myModalViewController") as! myModalViewController
modalViewController.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
let navController = UINavigationController(rootViewController: accountManager)
dispatch_async(dispatch_get_main_queue(),{
self.presentViewController(navController, animated: true, completion: nil)
})
我尝试通过多种方式修复此问题,包括将其移至上面的主线程。这对我有用:
在情节提要中,select 有问题的 table 视图,(select 它在文档大纲中以确保您得到了正确的东西。然后在属性检查器中您将能够看到 table 视图的属性以及它下面包含的滚动视图(所有 table 视图都基于滚动视图)。那里有一个叫做 "delays content touches" 的愚蠢的小框. 取消选中它。还有一个 "allows cancellable touches",我想您也想确保它也未选中,因为我认为双击会弄乱我的。
执行 segue 时似乎有多种情况无法正常工作。例如,如果您从展开转场的操作处理程序调用 performSegue
,您将 运行 陷入各种问题,即使您在主线程上也是如此。在我当前的项目中,我从 table 视图的 didSelectRowAt
方法调用 performSegue
。这是最基本的 segues 之一,当然我在主线程上,但我看到了 OP 描述的确切症状。
我不知道为什么在某些情况下会发生这种情况,而在其他情况下不会,但我发现使用 async
推迟 performSegue
调用可以解决所有潜在问题。这曾经看起来像是一个 hack,让我很紧张,但在这一点上,我有几个成熟的项目使用这种方法,现在它似乎是 "right" 进行手动 segue 的方法。
这是代码的 Swift 3 版本(请参阅其他帖子了解 Swift 2 和 Obj-C 版本):
DispatchQueue.main.async {
self.performSegue(withIdentifier: "theIdentifier", sender: theSender)
}
似乎(在我看来...)只有当单元格 selectionType
不是 .none
时才会出现此问题。
您可以将其更改为任何其他选项(在情节提要 Attribute inspector
中,设置 Selection
字段)并且它会正常工作(对我有用...)。
缺点是它弄乱了单元格 UI.
您可以在 UITableViewDelegate
的 didSelect
委托函数中调用 DispatchQueue.main.async{}
块中的 segue,如前所述。
我使用了第一个解决方案并在单元格本身添加了 -
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(false, animated: false)
}
这将使单元格 'highlight' 在水龙头处,但它会立即 return 到通常的 UI 并且对我来说没问题...
对于通过子类化组织代码的开发人员,我得出了一个非常简单的解决方案,我想分享 (Swift 4):
import UIKit
class ABCViewController: UIViewController {
// ... Other useful methods like overriding deinit and didReceiveMemoryWarning
// Performs a segue on the main thread to ensure it will
// transition once a UI-slot is available
func performSegueOnMainThread(with identifier: String, sender: Any?) {
DispatchQueue.main.async {
self.performSegue(with: identifier, sender: sender)
}
}
}
然后,只需从您的实现中调用它:
myViewController.performSegueOnMainThread(with: "ShowDetailsSegue", sender: self)
对我来说,我的下一个视图中有太多 "Clear" 彩色视图,所以当 segue 动画化时,它似乎因此而延迟。我遍历了视图控制器的 UI 层次结构,寻找清晰的颜色并将它们替换为纯黑色或纯白色,并确保 alpha 为 1(如果不需要的话)。我的延迟现在消失了,我的模态呈现也很流畅。
我有一个简单的 table 视图,我在其中处理 table 视图上的 select 操作。此操作遵循一个 segue。
如果 segue 是 push
segue,下一个视图会立即显示。
如果 segue 是 modal
segue,下一个视图要么:
- 显示需要 6 秒左右
- 如果我再次点击(第二次点击)会立即显示
我试着四处寻找一些想法,但 none 似乎适用于我的情况。特别是:
- 我正在主 UI 线程上执行 segue
- 我的看法很简单(所以
viewDidLoad
没有问题)。再加上它在 segue 为push
时几乎瞬间显示的事实表明加载目标视图没有问题 - 我尝试将
nil
传递给sender
;同样的效果。
有人对此有什么想法吗?
相信我,试试这个。我 运行 遇到过这个问题几次。
在Swift 2:
dispatch_async(dispatch_get_main_queue(),{
self.performSegue(withIdentifier:mysegueIdentifier,sender: self)
})
或 Swift 3:
DispatchQueue.main.async {
self.performSegue(withIdentifier: mysegueIdentifier,sender: self)
}
正如所讨论的 here and here。
接受的解决方案对我有用。 Swift 2.0 的代码更新如下:
dispatch_async(dispatch_get_main_queue(),{
self.performSegueWithIdentifier(mysegueIdentifier, sender:self)
})
希望对您有所帮助,您可以在 Swift 中以编程方式创建模式转换:
let myStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let modalViewController = myStoryboard.instantiateViewControllerWithIdentifier("myModalViewController") as! myModalViewController
modalViewController.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
let navController = UINavigationController(rootViewController: accountManager)
dispatch_async(dispatch_get_main_queue(),{
self.presentViewController(navController, animated: true, completion: nil)
})
我尝试通过多种方式修复此问题,包括将其移至上面的主线程。这对我有用:
在情节提要中,select 有问题的 table 视图,(select 它在文档大纲中以确保您得到了正确的东西。然后在属性检查器中您将能够看到 table 视图的属性以及它下面包含的滚动视图(所有 table 视图都基于滚动视图)。那里有一个叫做 "delays content touches" 的愚蠢的小框. 取消选中它。还有一个 "allows cancellable touches",我想您也想确保它也未选中,因为我认为双击会弄乱我的。
执行 segue 时似乎有多种情况无法正常工作。例如,如果您从展开转场的操作处理程序调用 performSegue
,您将 运行 陷入各种问题,即使您在主线程上也是如此。在我当前的项目中,我从 table 视图的 didSelectRowAt
方法调用 performSegue
。这是最基本的 segues 之一,当然我在主线程上,但我看到了 OP 描述的确切症状。
我不知道为什么在某些情况下会发生这种情况,而在其他情况下不会,但我发现使用 async
推迟 performSegue
调用可以解决所有潜在问题。这曾经看起来像是一个 hack,让我很紧张,但在这一点上,我有几个成熟的项目使用这种方法,现在它似乎是 "right" 进行手动 segue 的方法。
这是代码的 Swift 3 版本(请参阅其他帖子了解 Swift 2 和 Obj-C 版本):
DispatchQueue.main.async {
self.performSegue(withIdentifier: "theIdentifier", sender: theSender)
}
似乎(在我看来...)只有当单元格 selectionType
不是 .none
时才会出现此问题。
您可以将其更改为任何其他选项(在情节提要 Attribute inspector
中,设置 Selection
字段)并且它会正常工作(对我有用...)。
缺点是它弄乱了单元格 UI.
您可以在 UITableViewDelegate
的 didSelect
委托函数中调用 DispatchQueue.main.async{}
块中的 segue,如前所述。
我使用了第一个解决方案并在单元格本身添加了 -
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(false, animated: false)
}
这将使单元格 'highlight' 在水龙头处,但它会立即 return 到通常的 UI 并且对我来说没问题...
对于通过子类化组织代码的开发人员,我得出了一个非常简单的解决方案,我想分享 (Swift 4):
import UIKit
class ABCViewController: UIViewController {
// ... Other useful methods like overriding deinit and didReceiveMemoryWarning
// Performs a segue on the main thread to ensure it will
// transition once a UI-slot is available
func performSegueOnMainThread(with identifier: String, sender: Any?) {
DispatchQueue.main.async {
self.performSegue(with: identifier, sender: sender)
}
}
}
然后,只需从您的实现中调用它:
myViewController.performSegueOnMainThread(with: "ShowDetailsSegue", sender: self)
对我来说,我的下一个视图中有太多 "Clear" 彩色视图,所以当 segue 动画化时,它似乎因此而延迟。我遍历了视图控制器的 UI 层次结构,寻找清晰的颜色并将它们替换为纯黑色或纯白色,并确保 alpha 为 1(如果不需要的话)。我的延迟现在消失了,我的模态呈现也很流畅。