SwiftUI GeometryReader вызывает утечку памяти - PullRequest
0 голосов
/ 22 января 2020

Рассмотрим следующий код:

import SwiftUI

class ViewModel: ObservableObject {
}

struct TestView: View {
    @ObservedObject var vm = ViewModel()

    var body: some View {
//        self.sample
        GeometryReader { _ in
            self.sample
        }
    }

    var sample: some View {
        Text("Hello, World!")
    }
}

struct Tabs : View {
    @State var selection: Int = 0

    var body: some View {
        TabView(selection: $selection) {
            TestView().tabItem {
                Text("First Tab")
            }
            .tag(0)

            Text(String(selection))
            .tabItem {
                Text("Second Tab")
            }
            .tag(1)
        }
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}

Есть две вкладки, и в теле указывается выбор, поэтому тело будет вызываться при изменении выбора. TestView использует GeometryReader. Когда я переключаюсь с «Первая вкладка» на «Вторая вкладка», ViewModel создается снова и никогда не разыменовывается. Это неожиданно. Если я переключусь 100 раз, у меня будет 100 ViewModels, на которые ссылаются внутренние компоненты SwiftUI.

Хотя, если я удаляю GeometryReader, он работает как положено.

Кто-то испытывал это? Есть ли обходные пути? Я просто хочу, чтобы это время жизни ViewModel было привязано к времени жизни TestView.

ОБНОВЛЕНИЕ:

XCode 11.3.1 iOS 13.3

1 Ответ

1 голос
/ 22 января 2020

Хорошо, давайте внесем следующие изменения в ViewModel

class ViewModel: ObservableObject {
    init() {
        print(">> inited") // you can put breakpoint here in Debug Preview
    }
}

, так что теперь видно, что поскольку представление является типом значения

struct TestView: View {
    @ObservedObject var vm = ViewModel() // << new instance on each creation
    ...

и оно происходит от

var body: some View {
    TabView(selection: $selection) {
        TestView().tabItem { // << created on each tab switch
        ...

Итак, решением будет ViewModel создание из TestView и внедрение внешнего экземпляра либо с помощью .environmentObject, либо с помощью аргументов конструктора.

Кстати, это не зависит от GeometryReader. Протестировано с Xcode 11.2.1 / iOS 13.2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...