【问题标题】:Swift self.performSegueWithIdentifier randomly won't workSwift self.performSegueWithIdentifier 随机不起作用
【发布时间】: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 的那个)的控制器也包含在其中吗?从哪个视图控制器实现了 unwind IBAction 的问题中不清楚。
  • 另外,您正在从层次结构中转换的视图控制器的特定实例(通过打印 self 来确认实际内存地址)是否也在层次结构中?
  • 您可以将IBAction 移动到InitialViewController 中,然后执行您需要的任何操作来从那里显示登录视图控制器。或者使登录成为模态转换并从您所在的任何地方登录。这仅取决于您如何实现登录过程。但是展开转场总是必须是 IBAction 到现有层次结构中的视图控制器。

标签: ios swift


【解决方案1】:

如果在视图控制器层次结构中的任何视图控制器中都找不到 unwind segue IBAction 方法,就会发生这种情况。发生这种情况的原因有很多。也许有问题的视图控制器根本不在视图控制器层次结构中。或者,您从一个视图控制器转换到另一个视图控制器时,您的视图控制器层次结构与您的视图层次结构保持同步(例如,如果您曾经通过将一个视图控制器的视图 addSubview 转换到另一个视图控制器,而没有执行必要的addChildViewController 电话)。或者,也许您在某处手动更换了根视图控制器。但是,归根结底,以某种方式,以某种方式,在现有视图控制器层次结构中的任何视图控制器中都找不到您用于展开转场的 IBAction

关键是首先找到发生这种情况的情况。 (我知道你说它很难重现,但请继续尝试,直到你的问题出现。)一旦你这样做了,暂停执行并查看视图控制器层次结构。例如,点击调试器中的“暂停”按钮(或添加断点)并打印视图层次结构,如果在 Swift 框架中,则在 (lldb) 提示符处输入以下内容:

expr -l objc++ -O -- [UIViewController _printHierarchy]

或者如果在 Objective-C 框架中,只需:

po [UIViewController _printHierarchy]

例如:

确保您的目标视图控制器出现在视图控制器层次结构中。它很可能不存在,一旦你确认了这个问题,你必须回溯并弄清楚有问题的视图控制器是如何最终从视图控制器层次结构中被忽略的。如果您查看应用程序中发生的所有视图控制器转换,您可能会发现其中一个没有执行标准转换。

【讨论】:

  • 感谢您的建议。我将命令的输出放在原始问题中。有什么突出的
猜你喜欢
  • 2017-06-17
  • 2014-05-12
  • 2011-01-19
  • 2010-11-05
  • 1970-01-01
  • 2015-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多