首页 > 解决方案 > SwiftUI - 隐藏 LazyVGrid 会导致内存泄漏

问题描述

我有一个LazyVGrid显示从远程 API 获取的一些数据。LazyVGrid通过按下按钮隐藏时,我遇到了内存泄漏。这似乎只有在内容多于LazyVGrid.

在此处输入图像描述

我为您准备了一些代码来重现此泄漏。这段代码有什么不妥之处,还是苹果方面的错误?也许有解决方法?

import SwiftUI
import Foundation
import Combine

enum FakeAPI {
    static var fakeData: [Result] {
       return [
            Result(id: 1), Result(id: 2), Result(id: 3), Result(id: 4), Result(id: 5),
            Result(id: 6), Result(id: 7), Result(id: 8), Result(id: 9), Result(id: 10),
            Result(id: 11), Result(id: 12), Result(id: 13), Result(id: 14), Result(id: 15),
            Result(id: 16), Result(id: 17), Result(id: 18), Result(id: 19), Result(id: 20),
            Result(id: 21), Result(id: 22), Result(id: 23), Result(id: 24), Result(id: 25),
            Result(id: 26), Result(id: 27), Result(id: 28), Result(id: 29), Result(id: 30)
       ]
    }

    static func fetchData() -> AnyPublisher<[Result], Error> {
        return Just(fakeData)
            .mapError({ $0 as Error })
            .eraseToAnyPublisher()
    }
}

struct Result: Identifiable {
    let id: Int
}

struct ContentView: View {
    @StateObject private var vm: ViewModel = ViewModel()

    let columns = [
        GridItem(.adaptive(minimum: 200), alignment: .top),
        GridItem(.adaptive(minimum: 200), alignment: .top)
    ]

    var body: some View {
        NavigationView {
            ScrollView {
                Button {
                    vm.hide = true
                } label: {
                    Text("Hide")
                }
                if !vm.hide {
                    LazyVGrid(columns: columns) {
                        ForEach(vm.results) { result in
                            Text("\(result.id)")
                                .frame(width: 120, height: 120)
                                .background(Color.red)
                        }
                    }
                }
            }
            .navigationTitle("Grid Memory Leak")
            .onAppear {
                vm.load()
            }
        }
    }
}

final class ViewModel: ObservableObject {
    @Published private(set) var results: [Result] = []
    @Published var hide = false

    private var subscriptions = Set<AnyCancellable>()

    func load() -> Void {
        FakeAPI.fetchData()
            .sink(receiveCompletion: { _ in }, receiveValue: { [weak self] results in
                self?.results = results
            })
            .store(in: &subscriptions)
    }
}

标签: swiftmemory-leaksswiftui

解决方案


推荐阅读