gpt4 book ai didi

swift - 使用 URLSessionDataTask 和 @Published 的内存泄漏

转载 作者:行者123 更新时间:2023-12-05 06:07:23 25 4
gpt4 key购买 nike

我在我的 SwiftUI 应用程序中将此 APIRepresentative 类作为单例 EnvironmentObject。该类具有 @Published var,它按 ID 保存所有 InsightData 结构。

即使在不依赖于 insightData 的 View 中,重复调用 getInsightData 函数也会导致我的应用程序中的内存使用量每次增加约 200Kb 左右。在我的应用程序的整个生命周期中,这将导致内存使用量激增至数 GB。

关键在于:当我删除 insightData@Published 修饰符时,内存泄漏就消失了。然后我可以随心所欲地调用我的函数,而不会增加内存使用量。知道为什么会这样吗?我非常想保留 @Published 属性。

import Foundation
import Combine

final class APIRepresentative: ObservableObject {
private static let baseURLString = "https://apptelemetry.io/api/v1/"

@Published var insightData: [UUID: InsightDataTransferObject] = [:]

// More published properties
// ...
}


extension APIRepresentative {
func getInsightData(for insight: Insight, in insightGroup: InsightGroup, in app: TelemetryApp, callback: ((Result<InsightDataTransferObject, TransferError>) -> ())? = nil) {
let timeWindowEndDate = timeWindowEnd ?? Date()
let timeWindowBeginDate = timeWindowBeginning ?? timeWindowEndDate.addingTimeInterval(-60 * 60 * 24 * 30)

let url = urlForPath("apps", app.id.uuidString, "insightgroups", insightGroup.id.uuidString, "insights",
insight.id.uuidString,
Formatter.iso8601noFS.string(from: timeWindowBeginDate),
Formatter.iso8601noFS.string(from: timeWindowEndDate)
)

let request = self.authenticatedURLRequest(for: url, httpMethod: "GET")
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
let decoded = try! JSONDecoder.telemetryDecoder.decode(InsightDataTransferObject.self, from: data)

DispatchQueue.main.async { [weak self] in
guard let self = self else {
print("Self is gone")
return
}

var newInsightData = self.insightData
newInsightData[decoded.id] = decoded

self.insightData = newInsightData
}
}
}.resume()
}
}

// more retrieval functions for the other published properties
// ...

这是 full file但我很确定我在这个精简版中包含了所有相关部分

最佳答案

首先,我假设内存会随着这条线增长:

        self.insightData[decoded.id] = decoded

您为每次下载存储新值,并且似乎永远不会释放它们,除非 decoded.id 重复。那不是泄漏;这只是在内存中存储更多数据。

就是说,如果您使用 while 循环对此进行测试,您应该预计内存会大幅增长,因为您永远不会耗尽自动释放池。当当前运行循环周期完成时自动释放池被清空,但是这个 while 循环永远不会结束。所以你想创建一个新的池:

while true {
@autoreleasepool {
api.getInsightData(for: insight, in: insightGroup, in: app)
sleep(1)
}
}

关于swift - 使用 URLSessionDataTask 和 @Published 的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65467950/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com