[英]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
變量-它的值與someFunctionWithNonescapingClosure
的self
值相同-存在您的周期。
在堆棧跟蹤中,您還將看到諸如“ 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.