所以我写了一些代码来更好地处理保留循环。
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 在 playground 中尝试此操作,将其初始化并将其分配给变量,然后将变量设置为 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
变量 - 它与 self
具有相同的值的 someFunctionWithNonescapingClosure
- 有你的周期。
在堆栈跟踪中,您还会看到诸如“部分应用”之类的条目 - 这是提供的参数 ( { 42 }
) 和隐式捕获的 self
的位置收集并传递给 someFunctionWithNonescapingClosure()
.
如果将代码更改为:
init()
{
closure = Cycle.someFunctionWithNonescapingClosure
}
static func someFunctionWithNonescapingClosure(closure: () -> Int)
{
print("Hello") // breakpoint on this line
}
即制作someFunctionWithNonescapingClosure
一个类 ( static
) 方法而不是一个实例,那么当前类实例不会在闭包中捕获,您将不会得到一个循环。
HTH
关于ios - Swift 中奇怪的保留周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50711659/