为什么我们需要一个weakSelf用于闭包中的函数/方法?

时间:2016-12-02 16:51:00

标签: swift memory-leaks closures

阅读my own answer。 我完全理解为什么我们需要为成员/属性提供weakSelf。他们可以创建内存周期。但属性有内存位置。 功能还有内存位置吗?!我的意思是不是一个功能只是在旅途中发生?如果是,那么内存位置类型是否与属性位置有什么不同?

如果我不使用self,我会收到此错误。

  

在闭包中调用方法'alertFunc'需要明确的'self'。至   使捕获语义显式化

与以下略有不同:

  

在闭包中引用属性'window'需要明确的'self'。至   使捕获语义显式化

我的代码如下:

let another = UIAlertAction(title: "Log", style:UIAlertActionStyle.Default){action in  
 logAction ()

 }

private func logAction () {

print("health")

}

2 个答案:

答案 0 :(得分:2)

来自于我从聚会上知道的iOS书呆子

tl; dr你需要将self用于实例方法,但 class 方法不需要它。一个类可能有很多实例,但它只能有一个自身声明(也包含它的类型/类/静态函数)。

为什么会出现错误1:请注意alertFunc可能有对某个属性的引用。

可能是:

private func logAction () {

    print("someProperty = \(self.someProperty)")

}

因此,在这种情况下,您最终会引用一个属性。

为什么会出现错误2:即使您的函数中没有对self的引用,仍然因为您将其作为实例方法编写,自我就是隐式传递。但是,我们没有看到!

实例方法实际上只是一个函数的语法糖,它接受第一个参数的实例,它是自动传递的。

在幕后,它可能看起来像这样的东西

private func alertFunc (_ instance: MyType) {

    print("someProperty = \(instance.someProperty)")

}

// and actually the call to it *may* look something like this:

MyType.someFunc(self)

我们从未看到自我被传递!这是一种欺骗我们的语法糖。

因此,如果你的方法不在内部使用self(即不以任何方式依赖于实例的状态)那么实际上最好使它成为static/type/class method或自由函数。

替代方案1:使用免费功能。

class someClass {

    ...

}

func freeFunc {
    print("Hi this is a free function, written outside the scope of any class...")
}

然后在你的关闭中,你使用freeFunc()

来调用它

替代方案2:使用班级功能。

class someClass {

    ...

     class private func alertFunc() {
          print("Hi this was a class function, see the class at the beginning of the func definition")
     }
 }

然后在你的关闭中,你使用yourClassName.alertFunc()

来调用它

但是,为什么类函数不会创建内存循环而实例函数呢?  我很高兴你问:

例如mehtods,对于您接触到的每个实例,都有一个 new 内存位置并生成一个 new 内存周期,该周期将持续解除分配。

对于类方法,每次接触类/类型方法时,都会触及相同类/类型方法,并且在持久化该类方法时,您将不会一遍又一遍地创建它,它只创建一次并完成!

在objective-C(和C ++)类型方法中:

当应用程序启动时,系统可以相当安全地预先分配所有指令  将那些类型的方法与它们的类指针一起放入内存中  因此,几乎没有任何开销一遍又一遍地调用那些 我想很快就会做同样的事情

答案 1 :(得分:2)

当您撰写logAction()时,它隐含地表示self.logAction()。 (在某些实例上调用方法;当您不指定时,它默认为self。)因此,您在闭包内使用self,这意味着闭包捕获self ,以及它是否捕获强或弱参考都会影响内存管理。