简体   繁体   English

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

[英]Getting a swift_unknownWeakRelease() in a possible block/closure retain cycle

I have a view controller that shows up at the start of my app to prepare the UIManagedDocument I'm using with Core Data. 我有一个视图控制器,显示在我的应用程序的开头,以准备我正在使用Core Data的UIManagedDocument。 Problem: I keep getting a swift_unknownWeakRelease() crash when I run the app on an iPhone 4S device with iOS 7.1. 问题:当我在iOS swift_unknownWeakRelease()的iPhone 4S设备上运行应用程序时,我一直遇到swift_unknownWeakRelease()崩溃。 Here's the code: 这是代码:

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()
            }
        }
    }

}

I suspected that there's a strong reference cycle between the block and self since that's the only place I can see it potentially happening. 我怀疑在块和self之间有一个强大的参考周期,因为这是我可以看到它可能发生的唯一地方。 True enough, if I change the capture list from [unowned self] to [weak self] or remove it altogether (keeping a strong reference to self inside the closure), the program continues just fine. 确实如此,如果我将捕获列表从[unowned self]更改为[weak self]或完全删除它(在闭包内保持对self的强引用),程序继续正常。 This error doesn't happen when I run the app on an iPhone 5 simulator with iOS 8, or a 5S simulator with iOS 7.1. 当我在带有iOS 8的iPhone 5模拟器或带有iOS 7.1的5S模拟器上运行应用程序时,不会发生此错误。

How can I write my code differently so that the crash is avoided across all devices running iOS 7.0+? 如何以不同的方式编写代码,以便在运行iOS 7.0+的所有设备上避免崩溃? I'm convinced that unowned is the correct modifier. 我确信unowned是正确的修饰符。 I expect self to still exist until the completionHandler is finished, so weak doesn't feel right. 我希望self仍然存在,直到completionHandler握手完成,所以weak感觉不对。 Here's the full log in the Debug Navigator if it helps: 如果有帮助,这是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

The problem here is with unowned reference. 这里的问题是无主参考。 When self is released, the block still retains self and so tries to call self which is nil. 当自我被释放时,该块仍然保留自我,因此试图调用自己是零。 Use weak in order to prevent this. 使用弱以防止这种情况。 Since weak is optional type inside block, you could use conditional unwrapping and execute other code as, 由于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()
        }
      }
    }
  }

}

I don't think that there could be problem with retain cycle. 我不认为保留周期可能存在问题。 prepareWithCompletionHandler closure parameter captures self , but self (instance of SetupViewController ) doesn't own the document variable. prepareWithCompletionHandler闭包参数捕获self ,但selfSetupViewController实例)不拥有文档变量。 You don't need to use capture list in this case. 在这种情况下,您不需要使用捕获列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM