簡體   English   中英

在Swift中奇怪的保留周期

[英]Weird retain cycle in Swift

所以我寫了一些代碼以更好地保持周期。

class AnotherViewController : UIViewController{

var closure : ((() -> Int) -> ())!


override func viewDidLoad() {
    super.viewDidLoad()

    closure = self.someFunctionWithNonescapingClosure

}

func someFunctionWithNonescapingClosure(closure: () -> Int) {
    //        closure()
}

}

因此,顯然,將viewController中的功能之一分配給屬性閉包,會引起保留周期問題。

但是我不知道怎么辦?

Self對Closure有很強的引用,但是,是否在viewController tp Closure中分配了一個函數,卻對self有很強的引用?

謝謝

編輯------

顯然,如果您在操場上通過創建AnotherViewController進行嘗試,將其初始化並將其分配給變量,然后將該變量設置為nil,它將成功地取消初始化AnotherViewController,但如果在應用程序中進行嘗試,AnotherViewController將不會成功取消初始化。

您可以嘗試將按鈕添加到AnotherViewController並將其關閉,為方便起見,按鈕代碼是這樣的

 private func addAButton(){
    let button = UIButton()
    let buttonBounds = CGRect(x: 0, y: 0, width: 200, height: 200)
    let buttonCenter = view.center
    button.bounds = buttonBounds
    button.center = buttonCenter

    view.addSubview(button)

    button.backgroundColor = .red

    button.addTarget(self, action: #selector(goBack), for: .touchUpInside)
}

@objc func goBack(){
    dismiss(animated: true, completion: nil)
}

您的closure被分配了一個實例方法,該方法隱式捕獲self ,因此捕獲了循環。

嘗試以下應用:

import Cocoa

class Cycle
{
  var closure : ((() -> Int) -> ())!

  init()
  {
     closure = self.someFunctionWithNonescapingClosure
  }

  func someFunctionWithNonescapingClosure(closure: () -> Int)
  {
     print("Hello") // breakpoint on this line
  }
}

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate
{
  @IBOutlet weak var window: NSWindow!

  func applicationDidFinishLaunching(_ aNotification: Notification)
  {
     let aCycle = Cycle()
     aCycle.closure({ 42 })
  }
}

print行上添加一個斷點並運行該應用程序。

該應用程序將停止內someFunctionWithNonescapingClosure()這是由稱為aCycle.closure({ 42 })

看變量顯示,有一個self 這是因為每個實例方法都有一個隱式的 self變量。

在您的代碼中,那個self是從哪里來的?

當行:

closure = self.someFunctionWithNonescapingClosure

被執行時,Swift捕獲self的當前值作為隱式參數傳遞給someFunctionWithNonescapingClosure() ,在您從實例方法創建閉包時必須執行此操作。

這樣便有了循環,分配給closure包含對self的引用。

要查看此注釋,請在調試器停止運行時選擇self的值,然后在堆棧跟蹤中選擇applicationDidFinishLaunching的條目,並查看其aCycle變量-它的值與someFunctionWithNonescapingClosureself值相同-存在您的周期。

在堆棧跟蹤中,您還將看到諸如“ partial apply”之類的條目-這是收集提供的參數( { 42 } )和隱式捕獲的self並將其傳遞給someFunctionWithNonescapingClosure()

如果將代碼更改為:

  init()
  {
     closure = Cycle.someFunctionWithNonescapingClosure
  }

  static func someFunctionWithNonescapingClosure(closure: () -> Int)
  {
     print("Hello") // breakpoint on this line
  }

那就是使someFunctionWithNonescapingClosure成為一個實例上的類( static )方法,而不是在閉包中捕獲當前的類實例,並且不會獲得循環。

HTH

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM