在可能的块/闭包保留周期中获取swift_unknownWeakRelease()

Mat*_*ros 4 iphone cocoa-touch ios automatic-ref-counting swift

我有一个视图控制器,显示在我的应用程序的开头,以准备我正在使用Core Data的UIManagedDocument.问题:swift_unknownWeakRelease()当我在iOS 4.1的iPhone 4S设备上运行应用程序时,我一直在崩溃.这是代码:

class SetupViewController: UIViewController {

    @IBOutlet weak var loadingView: UIActivityIndicatorView!

    override func viewDidAppear(animated: Bool)  {
        super.viewDidAppear(animated)
        let document = SPRManagedDocument.sharedDocument()

        document.prepareWithCompletionHandler {[unowned self] success in
            if success {
                self.dismissViewControllerAnimated(false, completion: nil)
            } else {
                self.loadingView.stopAnimating()
                UIAlertView(title: "Error", message: "Categories can't be loaded.", delegate: nil, cancelButtonTitle: "OK").show()
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

我怀疑这个区块之间有一个强大的参考周期,self因为这是我唯一可以看到的可能发生的地方.确实如此,如果我将捕获列表更改[unowned self][weak self]或完全删除它(保持self对闭包内部的强引用),程序继续正常.当我在带有iOS 8的iPhone 5模拟器或带有iOS 7.1的5S模拟器上运行应用程序时,不会发生此错误.

如何以不同方式编写代码,以便在运行iOS 7.0+的所有设备上避免崩溃?我确信这unowned是正确的修饰符.我希望selfcompletionHandler完成之前仍然存在,所以weak感觉不对.如果有帮助,这是Debug Navigator中的完整日志:

Thread 1Queue : com.apple.main-thread (serial)
#0  0x0050c0ae in swift_unknownWeakRelease ()
#1  0x0012d760 in Spare.SetupViewController.(viewDidAppear (Spare.SetupViewController) -> (Swift.Bool) -> ()).(closure #1) at /Users/local.m.quiros/Development/spare-ios/Spare/View Controllers/SetupViewController.swift:28
#2  0x00108a8c in reabstraction thunk helper from @callee_owned (@unowned Swift.Bool) -> (@unowned ()) to @callee_owned (@in Swift.Bool) -> (@out ()) at /Users/local.m.quiros/Development/spare-ios/Spare/View Controllers/EditCategoryViewController.swift:180
#3  0x0012c68c in partial apply forwarder for reabstraction thunk helper from @callee_owned (@unowned Swift.Bool) -> (@unowned ()) to @callee_owned (@in Swift.Bool) -> (@out ()) ()
#4  0x00108ac4 in reabstraction thunk helper from @callee_owned (@in Swift.Bool) -> (@out ()) to @callee_owned (@unowned Swift.Bool) -> (@unowned ()) at /Users/local.m.quiros/Development/spare-ios/Spare/View Controllers/EditCategoryViewController.swift:180
#5  0x00108b18 in reabstraction thunk helper from @callee_owned (@unowned Swift.Bool) -> (@unowned ()) to @callee_unowned @objc_block (@unowned ObjectiveC.ObjCBool) -> (@unowned ()) at /Users/local.m.quiros/Development/spare-ios/Spare/View Controllers/EditCategoryViewController.swift:180
#6  0x00149e68 in __51-[SPRManagedDocument prepareWithCompletionHandler:]_block_invoke at /Users/local.m.quiros/Development/spare-ios/Spare/Objects/SPRManagedDocument.m:49
#7  0x3b4baf86 in _dispatch_barrier_sync_f_slow_invoke ()
#8  0x3b4b381e in _dispatch_client_callout ()
#9  0x3b4ba49e in _dispatch_main_queue_callback_4CF$VARIANT$mp ()
#10 0x3071b8a0 in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#11 0x3071a174 in __CFRunLoopRun ()
#12 0x30684ebe in CFRunLoopRunSpecific ()
#13 0x30684ca2 in CFRunLoopRunInMode ()
#14 0x355de662 in GSEventRunModal ()
#15 0x32fd114c in UIApplicationMain ()
#16 0x00167060 in main at /Users/local.m.quiros/Development/spare-ios/Spare/main.m:16
Run Code Online (Sandbox Code Playgroud)

San*_*eep 7

这里的问题是无主参考.当自我被释放时,该块仍然保留自我,因此试图调用自己是零.使用弱以防止这种情况.由于weak是块内的可选类型,你可以使用条件展开并执行其他代码,因为

class SetupViewController: UIViewController {

  @IBOutlet weak var loadingView: UIActivityIndicatorView!

  override func viewDidAppear(animated: Bool)  {
    super.viewDidAppear(animated)
    let document = SPRManagedDocument.sharedDocument()

    document.prepareWithCompletionHandler {[weak self] success in
      if let weakSelf = self{
        if success {
          weakSelf.dismissViewControllerAnimated(false, completion: nil)
        } else {
          weakSelf.loadingView.stopAnimating()
          UIAlertView(title: "Error", message: "Categories can't be loaded.", delegate: nil, cancelButtonTitle: "OK").show()
        }
      }
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案.我想添加一些链接,帮助我理解它:http://bit.ly/resolvingStrongReferenceCyclesForClosures(Apple的东西)和http://bit.ly/weakSelfAndStrongSelf(一些很酷的家伙). (2认同)