所以我写了一些代码来更好地保留周期。
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)
}
答案 0 :(得分:1)
您的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
的{{1}} - 有你的周期。
在堆栈跟踪中,您还会看到“部分应用”之类的条目 - 这是收集的参数(someFunctionWithNonescapingClosure
)和隐式捕获的{ 42 }
被收集并传递给self
的位置
如果您将代码更改为:
someFunctionWithNonescapingClosure()
这是使 init()
{
closure = Cycle.someFunctionWithNonescapingClosure
}
static func someFunctionWithNonescapingClosure(closure: () -> Int)
{
print("Hello") // breakpoint on this line
}
一个类(someFunctionWithNonescapingClosure
)方法而不是实例一,然后在闭包中没有捕获当前的类实例,你将不会得到一个循环。
HTH