ios - Swift 中奇怪的保留周期

标签 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 在 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/

相关文章:

swift - 我如何快速扩展 View

iphone - 将 ZeroMQ 交叉编译到 ARM 以用于 MonoTouch iPhone 应用程序配置设置

ios - 返回 TableView 后 TableView 重新加载行

objective-c - 如果我写一个自定义属性的getter方法,如果getter通过访问另一个对象的值返回一个值,KVO是否仍然运行?

swift - 如何在 Swift 的 collectionView 方法之外访问单元格的值?

swift - 从 NSUserDefaults 中的值更改主视图 Controller 背景颜色

ios - 使用 Swift 3,如何解析 JSON 文件以便可以全局访问数据?

ios - 如何更改导航项标题颜色

ios - 在 Realm 中查询具有反向关系的对象的正确方法

ios - swift语言如何在SingleTon类中设置NSDictionary