performSegue 并不总是转换,但 prepare(for:sender) 总是被调用
Posted
技术标签:
【中文标题】performSegue 并不总是转换,但 prepare(for:sender) 总是被调用【英文标题】:performSegue doesn't always transition, but prepare(for:sender) always called 【发布时间】:2017-06-22 19:20:25 【问题描述】:当performSegue
被调用时,我的应用程序并不总是切换到下一个视图控制器。但是,它总是会立即执行prepare(for:sender)
。
performSegue
在没有硬错误的情况下无法工作(并且仍然执行prepareForSegue
)?
是否存在我需要检查的源视图控制器应该处于的某种状态?
如果我延迟 10 秒(通过 asyncAfter
),就会发生转场。
场景
我正在尝试为新功能(集成到 Spotlight 搜索)重新调整工作 segue。如果应用程序留在详细视图中,则不会在我的 iPhone 上发生转换。 (该应用有一个 UISplitViewController 作为它的根视图控制器。)
但是,当
-
我在 iPad 上进行测试 - 即同时显示主视图和详细视图时。
当我将应用程序留在主视图时,我在 iPhone 上进行测试。
当我从详细信息屏幕测试我的 iPhone 见下面的代码:
-
详细信息屏幕消失(根据
popToRootViewController
)
显示主视图,并突出显示正确的行(包括显示“进入主视图”的 NSLog)
函数执行,包括prepare(for:sender)
,但从未显示详细视图。
此时,我可以点击相应的行,转场按预期发生 - 即 tableView(:didSelectRowAt:)
调用 performSegue
。
更多细节
Swift 3.0 和 ios 10
应用程序有一个 UISplitViewController 作为它的 rootViewController。主视图是一个带有食谱列表的 tableView。详细视图是一个 tableView,列出了所选配方的成分。 segue 从配方行选择过渡到其成分表。
我放入一个新功能:将食谱放入聚光灯,使用户可以搜索它们并在选择时,从主视图中选择配方,并在详细视图中显示其成分。
现在我正在尝试通过 appDelegate 的 application(:continue:restorationHandler)
实现 Spotlight 搜索集成:
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool
guard userActivity.activityType == CSSearchableItemActionType,
let userInfo = userActivity.userInfo,
let id = userInfo[CSSearchableItemActivityIdentifier] as? String
else
return false
// The id is a unique identifier for recipe.
if let inputRecipe = Recipe.getBy(uuid: id, moc: self.managedObjectContext)
let root = self.window?.rootViewController as! UISplitViewController
let nav = root.viewControllers[0] as! UINavigationController
// If this is a navigation controller, then detail is being shown
if (nav.topViewController as? UINavigationController) != nil
NSLog("Should be a detail view")
nav.popToRootViewController(animated: true)
if let masterVC = nav.topViewController as? RecipeMasterVC
NSLog("Into the master")
masterVC.selectTableRowAt(recipe: inputRecipe)
return true
在 RecipeMasterVC 中,我将此代码添加到 segue
func selectTableRowAt(recipe: Recipe)
let indexPath = self.fetchedResultsController.indexPath(forObject: recipe)
self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .top)
DispatchQueue.main.async
self.performSegue(withIdentifier: seguesEnum.RecipeDetail.rawValue, sender: recipe)
【问题讨论】:
主视图控制器可能尚未加载。视图控制器完全有可能存在 - 即已调用 init() 以便拆分视图控制器引用它,但尚未调用 viewDidLoad()。尝试在 viewDidLoad() 中添加一些调试代码或检查 selectTableRow 中的 isViewLoaded 方法以跟踪主视图何时实际加载。 @Dale - 在DispatchperformSegue
之前,self.isViewLoaded
的值为真。
我自己的应用程序中也有类似的场景,没有使用 segue,但仍然使用拆分视图。当我检查代码时,我发现我必须添加 200 毫秒的延迟才能使其工作。从来没有找到根本原因,但没有延迟,即使已经显示详细信息屏幕,即使调度异步也不起作用
会的。谢谢
【参考方案1】:
我自己的应用程序中也有类似的情况,没有使用 segue,但仍然使用拆分视图。当我检查代码时,我发现我必须添加 200 毫秒的延迟才能使其工作。从来没有找到根本原因,但没有延迟,即使已经显示详细信息屏幕,即使调度异步也不起作用
【讨论】:
以上是关于performSegue 并不总是转换,但 prepare(for:sender) 总是被调用的主要内容,如果未能解决你的问题,请参考以下文章
使用 performSegue 显示 navigationController