在Swift中保留奇怪的循环

时间:2018-06-06 03:01:59

标签: ios 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)
}

1 个答案:

答案 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