我创建了一个新应用,代表了我在实际应用中遇到的类似情况。基本上,我正在更新可观察对象的值,该对象用于呈现UI。并且由于某种原因导致内存在每次迭代中都保持增长。我还注意到,内存增长的数量取决于ContentView中的每秒迭代次数和视图数量/类型。
注意:正在更新的可观察对象是self.infoObj.text = "Counter: \(counter)"
AppDelgate.swift
func applicationDidFinishLaunching(_ aNotification: Notification) {
infoObj = InfoObj()
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView()
.environmentObject(infoObj)
// Create the window and set the content view.
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: contentView)
window.makeKeyAndOrderFront(nil)
var counter = 0;
DispatchQueue.global(qos: .userInteractive).async {
while(true) {
usleep(1000)
counter += 1
DispatchQueue.main.sync {
self.infoObj.text = "Counter: \(counter)"
}
}
}
}
ContentView.swift
struct ContentView: View {
@EnvironmentObject var infoObj: InfoObj
var body: some View {
VStack {
HStack {
Text("Text 11")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 12")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 13")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 14")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 15")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
Text(infoObj.text)
.frame(maxWidth: .infinity, maxHeight: .infinity)
HStack {
Text("Text 21")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 22")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 23")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 24")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 25")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
HStack {
Text("Text 31")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 32")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 33")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 34")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 35")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
HStack {
Text("Text 41")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 42")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 43")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 44")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 45")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
HStack {
Text("Text 51")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 52")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 53")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 54")
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("Text 55")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
class InfoObj: ObservableObject {
@Published var text = "initial"
}
您能帮助我理解这种情况发生的原因吗?我该如何解决呢?另外,为什么代码工具不将其视为内存泄漏?
答案 0 :(得分:1)
您只是同步地在堆栈上循环执行,因此您会观察到堆栈不断增长(不会作为泄漏的内存处理)。
解决方案是改为进行异步计数器处理并将所有内容移入EnvironmentObject
class InfoObj: ObservableObject {
private var counter = 0
@Published var text = "initial" {
didSet {
print(">> " + text) // << used for testing
}
}
func runCounter() {
counter += 1
text = "Counter: \(self.counter)"
// !! There is no sense to update UI with 1 milisecond
// (but you can tune interval below as you need)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05, execute: runCounter)
}
}
并使用
// ... other code
window.contentView = NSHostingView(rootView: contentView)
window.makeKeyAndOrderFront(nil)
infoObj.runCounter() // << here !!
}