Lazy initialisation and retain cycle 延迟初始化和内存循环引用

9 浏览
0 Comments

Lazy initialisation and retain cycle 延迟初始化和内存循环引用

在使用懒加载初始化器时,是否有可能出现保留循环的情况?

在一篇博文和许多其他地方中都可以看到[unowned self]

class Person {

var name: String

lazy var personalizedGreeting: String = {

[unowned self] in

return "你好,\(self.name)!"

}()

init(name: String) {

self.name = name

}

}

我尝试了这样做

class Person {

var name: String

lazy var personalizedGreeting: String = {

//[unowned self] in

return "你好,\(self.name)!"

}()

init(name: String) {

print("person init")

self.name = name

}

deinit {

print("person deinit")

}

}

像这样使用它

//...

let person = Person(name: "姓名")

print(person.personalizedGreeting)

//..

结果发现打印出了"person deinit"。

所以看起来没有保留循环。

根据我的了解,当一个闭包捕获self,并且该闭包被self强引用时,就会出现保留循环。这种情况看起来类似于保留循环,但实际上并不是。

0
0 Comments

懒初始化和保持循环引用是一个常见的问题,当在闭包中使用self时,可能会导致保持循环引用,从而导致内存泄漏。下面是这个问题出现的原因以及解决方法的总结。

原因:

当在闭包中使用self时,闭包会对self进行强引用,而self又对闭包进行强引用,这样就形成了保持循环引用。

解决方法:

1. 使用weak self或unowned self来避免保持循环引用。在闭包中使用weak self时,需要注意使用可选绑定来解包可选类型。

2. 使用捕获列表来声明闭包中对self的引用方式。捕获列表会在闭包的定义中声明对self的引用方式,可以通过捕获列表中声明的引用方式来避免保持循环引用。

以下是一个示例代码,演示了如何解决懒初始化和保持循环引用的问题:

lazy var personalizedGreeting: String = { [weak self] in

guard let self = self else { return "" }

return self.name

}()

在上述代码中,使用了捕获列表来声明对self的引用方式,将self声明为weak self,然后在闭包中使用可选绑定来解包可选类型。这样就避免了保持循环引用的问题。

懒初始化和保持循环引用是一个常见的问题,可以通过使用weak self或unowned self来避免保持循环引用。另外,也可以使用捕获列表来声明对self的引用方式。通过这些解决方法,可以避免内存泄漏和其他与保持循环引用相关的问题。

0
0 Comments

懒加载(Lazy initialisation)和循环引用(retain cycle)是iOS开发中常见的问题。懒加载是一种延迟初始化的方式,它可以在需要的时候才创建对象,而不是在对象被实例化时就立即创建。循环引用是指两个或多个对象之间相互持有对方的强引用,导致它们无法被释放,从而造成内存泄漏。

在上述代码示例中,我们可以看到两个问题的出现原因和解决方法。首先,懒加载的闭包在执行时会捕获self(当前对象)作为强引用,这导致了循环引用的产生。其次,如果闭包中的self被捕获为强引用,那么在对象释放之前,闭包是不会被释放的。

解决循环引用的方法是使用捕获列表(capture list),将self捕获为弱引用(weak reference)或无主引用(unowned reference)。这样在闭包中引用self时,不会造成循环引用。在上述代码示例中,如果将懒加载的闭包中的self捕获为无主引用(unowned),就可以避免循环引用的问题。

另外,对于懒加载的闭包,默认情况下并不会自动将self捕获为弱引用或无主引用。如果想要避免循环引用,需要手动将self捕获为弱引用或无主引用。

总结起来,懒加载和循环引用是iOS开发中常见的问题。懒加载可以延迟初始化对象,但如果在懒加载的闭包中捕获self为强引用,就会导致循环引用的产生。为了解决循环引用的问题,可以使用捕获列表将self捕获为弱引用或无主引用。

0
0 Comments

懒加载和循环引用问题的原因在于懒加载属性只保留了block的返回值,而没有保留block本身。因此,当懒加载属性未初始化时,外部上下文会保留懒加载的block,使其保持一致性,从而避免了循环引用的发生。然而,当懒加载属性被初始化后,懒加载的block会被执行并很快释放,这样也不会发生循环引用。

然而,问题的关键在于谁保留了懒加载的block。我认为这可能不是self,因为如果在block内部捕获self时没有发生循环引用,那么self可能不会保留懒加载的block。至于,我不这样认为。并不意味着没有捕获,而是意味着临时存在,并且没有对象应该对这个block有持久的引用,或者换句话说,保留这个block。这个block不能被异步使用(参考此主题)。如果是这样的话,懒加载的block如何保持到懒加载属性被初始化的时候呢?

解决这个问题的方法是使用weak self来避免循环引用。通过在block内部使用weak self,可以防止self对block的强引用,从而解决循环引用的问题。下面是一种可能的实现方式:

lazy var someProperty: SomeType = { [weak self] in

// 使用weak self来避免循环引用

guard let strongSelf = self else {

return DefaultValue

}

// 在这里使用strongSelf而不是self

// 进行其他操作

return someValue

}()

0