将闭包作为参数传递给singleton时的Swift内存管理

时间:2017-01-05 11:06:00

标签: ios swift memory-management singleton retain-cycle

我知道closure如果将retain cycles分配给类的属性并且在闭包内部使用类的实例属性,则可以创建MySingleton.classMethod(parameters ..., completion: { () -> Void in /** doing stuff here */ }) 。但

1)闭包没有分配给类属性但是作为参数传递给单例的类方法?

2)在这种情况下如何管理内存?

在我的控制器(UIViewController)的方法中,我有类似的东西:

class MyApp extends Component {
  onButtonClicked{
    this.navRef.jumpForward();
  }
  render() {
    return(
      <Navigator
        ref={navRef => this.navRef = navRef}
        initialRoute={{ title: 'Awesome Scene', index: 0 }}
        renderScene={(route, navigator) =>
        <Text>Hello {route.title}!</Text>
        }
       style={{padding: 100}}
      />
    );
  }
}

1 个答案:

答案 0 :(得分:5)

如果你没有将闭包赋值给属性,只是将它传递给函数你需要考虑闭包是否会转义或noescape。默认情况下,在Swift 3中,传递给函数的所有闭包都是非转义的。

以下是关于此事的更多信息:

“noescape” - 在函数返回之前调用传递的闭包

“escaping” - 如果一个闭包作为一个参数传递给一个函数,并且在函数返回后调用它,那么闭包就会转义。

简单的解释:当我们将闭包传递给函数时,我们需要将闭包标记为转义,并且在此函数返回后将调用闭包。

一般规则是关闭转义时你需要使用捕获列表来阻止保留周期。

实施例

let closure = { [weak someVariable] (name: Type) -> Void in
....
// code
}

其他信息:

一个奇怪的事情是可选的闭包被视为逃避。当我们显式添加转义关键字时,有一个编译错误-escaping属性仅适用于函数类型。

有关详细信息,请参阅以下链接。

https://bugs.swift.org/browse/SR-2053

https://stackoverflow.com/a/39619298/5388473

https://stackoverflow.com/a/39846519/5388473

<强>更新
在转义闭包的捕获列表中使用弱或无主的想法是,本质上我们不知道传递的转义闭包会发生什么,它可能稍后从另一个函数调用,或者它可能存储在某个对象中,可能会导致强大的保留周期。

弱vs无主vs强抓?

有关详细信息,请查看Apple ARC docs

来自Apple文档:

  

Swift提供了两种方法来解决强引用周期   使用类类型的属性:弱引用和无主   引用。

     

弱引用和无主引用在引用周期中启用一个实例   引用另一个实例而不保持强势。   然后,实例可以在不创建强大的情况下相互引用   参考周期。

     

当另一个实例有较短时,请使用弱引用   生命周期 - 也就是说,可以先释放另一个实例。   当另一个实例具有相同的生命周期时,请使用无主引用   或更长的寿命。

请记住,弱方法会在代码中添加一个样板,并且会慢一些,因为ARC会在释放时添加用于将弱变量设置为nil的代码。选择弱或无主时,遵循上述规则是一种好习惯。