使用Swipe Gesture Recognizer与自定义容器视图控制器崩溃

时间:2017-12-01 03:46:04

标签: ios crash uicontainerview uiswipegesturerecognizer

XCode 9.1 iPhoneX模拟器 iPhone6 11.1.2

我浪费了几天试图追踪看似在内存损坏中出现的崩溃(因为它似乎每次都不同)。

我已将其缩小为使用带有滑动手势识别器的(简单)容器视图控制器。

enter image description here

您可以在导航栏中看到两个(左和右)滑动手势识别器以及两个(上一个和下一个)按钮。 UIViewController有一个简单的UILabel

手势识别器配置为:

enter image description here

转换由以下人员执行:

  private func addViewToLayout(view: UIView) {
    let views = ["view": view]

    view.translatesAutoresizingMaskIntoConstraints = false
    container.addSubview(view)

    container.addConstraints(
        NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|",
        options:NSLayoutFormatOptions.alignAllLeft, metrics:nil, views:views))
    container.addConstraints(
        NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|",
        options:NSLayoutFormatOptions.alignAllLeft, metrics:nil, views:views))
  }

  private func transition(direction: Direction = .left) {
    let controllerPrevious = childViewControllers.first

    if let controllerNext = storyboard?.instantiateViewController(
        withIdentifier: "Test") {
      addChildViewController(controllerNext)
      addViewToLayout(view: controllerNext.view)

      if let controllerPrevious = controllerPrevious {
        controllerNext.view.transform = startTransform(direction: direction)

        UIView.animate(withDuration: transitionDuration,
            animations: {
              controllerNext.view.transform = CGAffineTransform.identity
              controllerPrevious.view.transform =
                  self.endTransform(direction: direction)
            },
            completion: { (finished: Bool) in
              controllerPrevious.view.removeFromSuperview()
              controllerPrevious.removeFromParentViewController()
              controllerNext.didMove(toParentViewController: self)
            })
      }
    }
  }

崩溃可能发生在转换期间/之后或导航离开Container View Controller之后。调试器通常在主线程中结束,没有有意义的堆栈跟踪。

enter image description here

崩溃相对容易造成,但并不总是来自同一行动,例如: (通过在设备上运行获得的日志):

EXC_BAD_ACCESS (SIGSEGV)
KERN_INVALID_ADDRESS at 0x4054600000000000
Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x0000000180f68428 objc_msgSend + 8
1   UIKit                           0x000000018b40dda4 -[UIView _layoutConstraintCleanup] + 204

EXC_CRASH (SIGABRT)
0x0000000000000000, 0x0000000000000000
EXC_CORPSE_NOTIFY
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x000000018181d348 __pthread_kill + 8
1   libsystem_pthread.dylib         0x0000000181931344 pthread_kill$VARIANT$mp + 396
2   libsystem_c.dylib               0x000000018178cfb8 abort + 140
3   libsystem_malloc.dylib          0x0000000181863a08 nanozone_default_reader + 0

请注意,如果仅使用导航栏中的按钮,则会发生 崩溃。

有什么能帮助找出崩溃的原因吗?

过渡后释放当前子视图控制器时,是否需要摆弄手势识别器?

question似乎有类似的症状,但并没有真正有用的建议。

修改

我已将展示崩溃的项目上传到Dropbox。编译项目,运行,点击下一步,多次左右两次轻触滑动,点击返回,点击下一步,重复直到崩溃。有时崩溃是立竿见影的,有时可能需要20次或更多次。

2 个答案:

答案 0 :(得分:0)

根据你提供的有限数据,看起来你有一个记忆碎片。

您应该使用Xcode提供的工具来调试此类问题并提供调查结果。使用项目的静态分析。与ASan,NSZombies,GuardMalloc等一起运行

如果您通过此类调查提供更多结果,则可以更轻松地帮助您确定后续步骤。

答案 1 :(得分:0)

这可能过于简单,但我遇到了Interface Builder和2次手指滑动的问题。当我分配1个手指时,它工作正常,但它在2个手指上崩溃。

如果我将它作为1个手指放在IB中并在viewDidLoad中将其更改为2个手指,我的问题就会消失。