Утечка памяти SwiftUI NavigationLink - PullRequest
4 голосов
/ 08 февраля 2020

У меня есть вопрос о том, как работает управление памятью в стеке SwiftUI NavigationView. У меня есть представление, в котором я объявил NavigationView и NavigationLink, внутри параметра назначения NavigationLink мой TestView. Навигация работает хорошо, но когда я выскакиваю из стека (например, кнопка «назад»), deinit не печатается в консоли, и TestViewModel все еще можно найти в графе памяти. Как деинициализировать мой TestViewModel, когда он больше не нужен?

    /// First view in application
    struct ContentView: View {

        var body: some View {
            NavigationView {
                VStack {
                    Text("Hello, leak!")
                    NavigationLink(
                        destination: TestView(viewModel: TestViewModel()),
                        label: { Text("Create leak ?‍♂️") }
                    )
                }
            }
        }
    }

    /// Just simple class for init and deinit print
    class TestViewModel: ObservableObject {

        @Published var text = "Test"

        init() {
            print("TestViewModel init")
        }

        deinit {
            print("TestViewModel deinit")
        }
    }

    /// Second view, which is poped from stack
    private struct TestView: View {

        @ObservedObject var viewModel: TestViewModel

        var body: some View {
            Text(viewModel.text)
        }
    }

ОБНОВЛЕНИЕ Добавлен снимок экрана с графиком памяти, который я заранее забыл.

Memory graph screenshot bottom part

Memory graph screenshot top part

ОБНОВЛЕНИЕ

Проверено на реальном устройстве, где работает навигация. Похоже, что модель представления не деинициализируется при всплывающем представлении, а инициализируется снова при нажатии в другой раз. Но вопрос все еще остается, есть ли способ деинформировать модель представления при выводе представления в стек навигации?

TestViewModel init
TestViewModel deinit
TestViewModel init

Кроме того, когда я добавляю другое представление в стек, поведение немного меняется. Теперь вторая модель представления вида вызовет утечку, но первая будет деинициализирована, как и ожидалось.

First view push
TestViewModel init
Second view push
TestViewModel2 init
Second view pop
First view pop
TestViewModel deinit
...