[英]Weird retain cycle in Swift
so I have written some codes to better under retain cycle. 所以我写了一些代码以更好地保持周期。
class AnotherViewController : UIViewController{
var closure : ((() -> Int) -> ())!
override func viewDidLoad() {
super.viewDidLoad()
closure = self.someFunctionWithNonescapingClosure
}
func someFunctionWithNonescapingClosure(closure: () -> Int) {
// closure()
}
} }
So apparently, assigning one of the function in viewController to the property closure, it causes the retain cycle problem. 因此,显然,将viewController中的功能之一分配给属性闭包,会引起保留周期问题。
But I don know how? 但是我不知道怎么办?
Self has a strong reference to Closure But, does assigning a function in the viewController tp Closure, make a strong reference of self to closure? Self对Closure有很强的引用,但是,是否在viewController tp Closure中分配了一个函数,却对self有很强的引用?
Thanks 谢谢
EDIT ------ 编辑------
Apparently, if you try this in a playground by creating the AnotherViewController, initialize it and assign it to a variable, then set the variable to nil, it will successfully deinit the AnotherViewController, but if you try it in an app, the AnotherViewController will not get deinited. 显然,如果您在操场上通过创建AnotherViewController进行尝试,将其初始化并将其分配给变量,然后将该变量设置为nil,它将成功地取消初始化AnotherViewController,但如果在应用程序中进行尝试,AnotherViewController将不会成功取消初始化。
You can try to add a button to AnotherViewController and dismiss it, for convenience, the button code is this 您可以尝试将按钮添加到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)
}
Your closure
is being assigned an instance method, which implicitly captures self
, hence the cycle. 您的
closure
被分配了一个实例方法,该方法隐式捕获self
,因此捕获了循环。
Try the following app: 尝试以下应用:
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 })
}
}
Add a breakpoint on the print
line and run the app. 在
print
行上添加一个断点并运行该应用程序。
The app will stop inside someFunctionWithNonescapingClosure()
which is called by aCycle.closure({ 42 })
. 该应用程序将停止内
someFunctionWithNonescapingClosure()
这是由称为aCycle.closure({ 42 })
Look at the variable display, there is a self
. 看变量显示,有一个
self
。 This is because every instance method has an implicit self
argument. 这是因为每个实例方法都有一个隐式的
self
变量。
In your code where does that self
come from? 在您的代码中,那个
self
是从哪里来的?
When the line: 当行:
closure = self.someFunctionWithNonescapingClosure
is executed Swift captures the current value of self
to pass as the implicit argument to someFunctionWithNonescapingClosure()
, it must do this as you are creating a closure from an instance method. 被执行时,Swift捕获
self
的当前值作为隐式参数传递给someFunctionWithNonescapingClosure()
,在您从实例方法创建闭包时必须执行此操作。
And so you have your cycle, the closure assigned to closure
contains a reference to self
. 这样便有了循环,分配给
closure
包含对self
的引用。
To see this note the value of self
when the debugger stops and then select the entry for applicationDidFinishLaunching
in the stack trace and look at its aCycle
variable - it has the same value as the self
of someFunctionWithNonescapingClosure
- there is your cycle. 要查看此注释,请在调试器停止运行时选择
self
的值,然后在堆栈跟踪中选择applicationDidFinishLaunching
的条目,并查看其aCycle
变量-它的值与someFunctionWithNonescapingClosure
的self
值相同-存在您的周期。
In the stack trace you will also see entries like "partial apply" - this is where the supplied argument ( { 42 }
) and the implicitly captured self
are collected and passed to someFunctionWithNonescapingClosure()
. 在堆栈跟踪中,您还将看到诸如“ partial apply”之类的条目-这是收集提供的参数(
{ 42 }
)和隐式捕获的self
并将其传递给someFunctionWithNonescapingClosure()
。
If you change the code to: 如果将代码更改为:
init()
{
closure = Cycle.someFunctionWithNonescapingClosure
}
static func someFunctionWithNonescapingClosure(closure: () -> Int)
{
print("Hello") // breakpoint on this line
}
that is make someFunctionWithNonescapingClosure
a class ( static
) method instead on an instance one then the current class instance is not captured in the closure and you will not get a cycle. 那就是使
someFunctionWithNonescapingClosure
成为一个实例上的类( static
)方法,而不是在闭包中捕获当前的类实例,并且不会获得循环。
HTH HTH
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.