Swift结构体内存泄漏

14 浏览
0 Comments

Swift结构体内存泄漏

我们尽可能使用Swift结构体。我们还使用RxSwift,它有需要使用闭包的方法。当我们有一个创建引用到self的闭包的结构体时,会创建一个强引用循环

import Foundation
import RxSwift
struct DoesItLeak {
    var someState: String = "initial value"
    var someVariable: Variable = Variable("some stuff")
    let bag = DisposeBag()
    mutating func someFoo() {
        someVariable.subscribeNext { person in
            self.someState = "something"
        }
        .addDisposableTo(bag)
    }
}

我怎么知道这个呢?如果我创建100,000个DoesItLeak对象并在它们中的每一个上调用someFoo(),我相信我有100,000个具有强引用循环的对象。换句话说,当我摆脱包含这些对象的DoesItLeak数组时,这些对象仍然留在内存中。如果我不调用someFoo(),就没有问题。

Variable是一个类。因此,我可以使用Xcode的Instruments的Allocations并过滤Variable字符串来看到这个内存问题。

\"Filtering

\"enter

如果我尝试使用[weak self],如下所示,我会收到编译器错误:

someVariable.subscribeNext { [weak self] person in

编译器错误是\"无法将弱引用应用于非类类型\"

在真实/非示例代码中,我们通过self访问方法和变量,这是一个内存问题。

我如何解决这个内存问题,同时保持DoesItLeak结构体?

感谢您的帮助。

admin 更改状态以发布 2023年5月23日
0
0 Comments

对于仍然面临这个问题的人。

  1. [weak self] 是不可能的,因为Struct是值类型而不是引用类型,所以没有指针。

  2. 这里泄漏的主要问题是你正在尝试访问结构属性self.someState = something内部完成的块,这将在赋值时基本上创建一个新的结构副本。

您不应在完成块内访问Struct属性。

0
0 Comments

正如达伦在评论中所述:“DoesItLeak不能是struct”,我们不能将DoesItLeak作为struct并安全地解决强引用循环问题。

值类型,如struct,存在于堆栈框架中。Closures和classes是引用类型。

正如Strong Reference Cycles for Closures一章所述:

这个强引用循环的发生是因为closures和classes都是引用类型。

由于struct具有Variableclass和闭包引用self存储在Variable class中使用subscribeNext,它创建了强引用循环。请查看Apple文档中“解决闭包的强引用循环”中的Automatic Reference Counting

0