【发布时间】:2016-05-22 17:15:01
【问题描述】:
在我的代码中,我定义了一个函数,它是在侧边菜单上执行的操作的委托,因此当您点击菜单中的注销操作时,menuDelegate?.selectionDelegate(Actions.Logout) 将被执行,下面的函数是处理回调的委托:
@objc func sideMenuAction(action: action) {
if(action == .Logout){
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.performSegueWithIdentifier("unwindToLogin", sender: self)
})
}
}
9 out of 10 次这工作正常,并且预期的结果是用户被退回到登录视图控制器,该控制器在故事板中具有 unwindToLogin 标识符,来自导航堆栈中的任何位置。但是第一次它不起作用,当执行self.performSegueWithIdentifier 行时,什么也没有发生!没有错误或警告,当发生这种情况时,override func prepareForSegue 在行执行后不会被调用!
我注意到的另一件事是,当触发此问题时,CPU 使用率仍保持在 100% 以上。应用程序通常的 CPU 使用率最高为 30%/40%,持续时间不超过 1/2 秒。
很难重现,当它发生时,我无法弄清楚发生了什么。在这里寻找一些提示来帮助调试可能的原因。
一旦我能够重现该问题,视图层次结构如下所示:
(lldb) expr -l objc++ -O -- [UIViewController _printHierarchy]
<SWRevealViewController 0x12585ea00>, state: appeared, view: <SWRevealView 0x1256f3c70>
| <demoApp.MenuViewController 0x12575daa0>, state: appeared, view: <UIView 0x12743e670>
| <UINavigationController 0x126047000>, state: appeared, view: <UILayoutContainerView 0x125755270>
| | <demoApp.InitialViewController 0x125760050>, state: disappeared, view: <UIView 0x1256e2b30> not in the window
| | <demoApp.MainViewController 0x1257f11f0>, state: disappeared, view: <UIView 0x1257f8df0> not in the window
| | <demoApp.DetailViewController 0x127617250>, state: appeared, view: <UIView 0x1274f2280>
我应该补充一点,应用程序有两个影响视图层次结构的流程:
Flow 1: User has never provided credential so Login View -> Initial View -> Main -> ......
Flow 2: User has already logged in once so Initial View -> Main -> .......
“unwindToLogin”标识符属于 Login View 控制器的 unwind IBAction
【问题讨论】:
-
只是出于好奇,你为什么选择使用dispatch_async?不是已经在主线程上执行了吗?
-
@AksharPatel 我偏执地认为它不工作的原因是在执行时我碰巧在一个侧面线程中,所以为了安全起见,我补充说看看它是否解决问题。这显然没有帮助。
-
您已经添加了视图控制器层次结构。太好了,带有 unwind
IBAction(不是您要转换的那个,而是您要展开 to 的那个)的控制器也包含在其中吗?从哪个视图控制器实现了 unwindIBAction的问题中不清楚。 -
另外,您正在从层次结构中转换的视图控制器的特定实例(通过打印
self来确认实际内存地址)是否也在层次结构中? -
您可以将
IBAction移动到InitialViewController中,然后执行您需要的任何操作来从那里显示登录视图控制器。或者使登录成为模态转换并从您所在的任何地方登录。这仅取决于您如何实现登录过程。但是展开转场总是必须是IBAction到现有层次结构中的视图控制器。