SwiftUI - возврат в стек навигации не освобождает представление - PullRequest
1 голос
/ 27 апреля 2020

Я хотел бы начать с выделения иерархии моих представлений. У меня просто есть FindUserView и WelcomeView.

FindUserView используется для извлечения пользователей с сервера, если введенная электронная почта существует. Если это так, то он автоматически перенаправляет меня к следующему WelcomeView, где я могу ввести пароль и логин.

Я создал репо здесь и видео SwiftUI - Pop назад не освобождает вид

Мой FindUserView: ---------------------------- и WelcomeView:

enter image description here ----------------- enter image description here

By нажимая кнопку NEXT на FindUserView, я получаю пользователя из базы данных:

func fetchUser(with email: String) {
        userService.getUser(with: email) { (result) in
            switch result {
            case .success(_):
                self.showActivityIndicator = false
                self.showingAlert = false
                self.showWelcomeView = true
                break
            case .failure:
                self.showingAlert = true
                break
            }
        }
    }

Я использую NavigationView и программно показываю WelcomeView, изменяя состояние showWelcomeView выше:

NavigationLink(destination: WelcomeView(), isActive: $showWelcomeView) { EmptyView() }

Теперь я нахожусь в режиме приветствия WelcomeView.

Но когда я нажимаю эту кнопку и возвращаюсь назад, мой WelcomeView все еще существует.

enter image description here

Поскольку я использую @EnvironmentObject с наблюдаемым состоянием свойства, я вижу, как оно отражается на представлении, которое уже отклонено. Это правильное поведение? Или мне нужно как-то иметь дело c WelcomeView? Приводит ли это к утечкам памяти?

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

1 Ответ

0 голосов
/ 27 апреля 2020

На самом деле неясно, является ли это дефектом или нет - представления SwiftUI являются значениями, поэтому для них нет deallo c. Похоже, что NavigationView просто сохраняет переменную типа lastView , пока она не будет заменена другой. Возможно, стоит отправить отзыв в Apple.

Между тем вот решение, которое позволяет отложить создание реального места назначения до тех пор, пока точно не будет нажата NavigationLink и не произведено его очистка (с любыми связанными ресурсами, такими как модель представления), когда представление удалено из стек с помощью кнопки «Назад».

Протестировано с Xcode 11.4 / iOS 13.4

Помощник прокси-сервера представления представления:

struct LinkPresenter<Content: View>: View {
    let content: () -> Content

    @State private var invlidated = false
    init(@ViewBuilder _ content: @escaping () -> Content) {
        self.content = content
    }
    var body: some View {
        Group {
            if self.invlidated {
                EmptyView()
            } else {
                content()
            }
        }
        .onDisappear { self.invlidated = true }
    }
}

Использование:

NavigationLink(destination: LinkPresenter { WelcomeView() }, 
    isActive: $showWelcomeView) { EmptyView() }
...