Сброс NavigationSplitView, когда приложение переходит в фоновый режим

Я пытался создать приложение с использованием NavigationSplitView и SwiftUI на iOS 16. Я заметил, что почти как только приложение переходит в фоновый режим (иногда мне приходится подождать несколько секунд, прежде чем немедленно снова открыть приложение), содержимое NavigationSplitView становится перезагрузить. Это поведение отличается от NavigationStack, использующего по существу тот же путь и структуру приложения. Мне интересно, есть ли у кого-нибудь идеи, почему это происходит?

Я провел небольшое расследование и могу сказать, что заметил несколько вещей.

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

Если использовать список без указанного параметра выбора, этот эффект смягчается, но представление все равно сбрасывается, а такие вещи, как положение прокрутки, стираются, несмотря на отсутствие изменения содержимого. Self._printChanges() указывает, что представление не изменилось, несмотря на сброс в исходное состояние.

Этот эффект воспроизводится с помощью собственного примера приложения Apple WWDC.

https://developer.apple.com/documentation/swiftui/bringing_robust_navigation_structure_to_your_swiftui_app

В этом примере приложения есть некоторая логика, которая пытается сохранить данные пути навигации, но на самом деле все равно не работает, но в целях тестирования я закомментировал это.

Внутри ContentView.swift

      //        .task {
//            if let jsonData = navigationData {
//                navigationModel.jsonData = jsonData
//            }
//            for await _ in navigationModel.objectWillChangeSequence {
//                navigationData = navigationModel.jsonData
//            }
//        }

Это приложение является хорошим примером, поскольку вы можете переключаться между NavigationStack и NavigationSplitView, а поведение изолировано от NavigationSplitView, и NavigationStack не сбрасывается немедленно.

Очевидно, сохранение состояния — это вариант, но он добавляет немало накладных расходов, а такие вещи, как положение прокрутки, трудно воспроизвести точно, и необходимость прибегать к этому, когда приложение теряет фокус всего на несколько секунд, не идеальна, мне интересно. есть ли обходной путь или это ошибка, тем более что этого не было при использовании NavigationStack. Я тестировал это на последней бета-версии iOS 17 с тем же эффектом.

Включая ссылку на видео, показывающую проблему https://youtu.be/cKicWv_58_s.

Я также попробовал создать небольшой пример приложения с использованием NavigationView с макетом из трех столбцов, и это работает нормально, поэтому кажется, что оно изолировано от NavigationSplitView.

Я также включил небольшой, более простой пример, чем приведенный ниже пример WWDC, который можно использовать для демонстрации проблемы и показывает, что NavigationView работает нормально.

      import SwiftUI

struct ContentView: View {
    @State var presentingNSV: Bool = false
    @State var presentingNV: Bool = false
    var body: some View {
        HStack {
            Button {
                presentingNSV.toggle()
            } label: {
                Text("NavigationSplitView")
            }
            Button {
                presentingNV.toggle()
            } label: {
                Text("NavigationView")
            }
        }
        .fullScreenCover(isPresented: $presentingNSV) {
            NSV(isPresented: $presentingNSV)
        }
        .fullScreenCover(isPresented: $presentingNV) {
            NV(isPresented: $presentingNV)
        }
    }
}

struct TestList: View {
    var body: some View {
        List(0..<1000) { item in
            Text("Item \(item)")
        }
    }
}

struct NSV: View {
    @Binding var isPresented: Bool
    var body: some View {
        let _ = Self._printChanges()
        NavigationSplitView {
            TestList()
            .toolbar {
                ToolbarItem {
                    Button {
                        isPresented = false
                    } label: {
                        Text("Back")
                    }
                }
            }
        } content: {
            TestList()
        } detail: {
            TestList()
        }
    }
}

struct NV: View {
    @Binding var isPresented: Bool
    var body: some View {
        let _ = Self._printChanges()
        NavigationView {
            TestList()
            .toolbar {
                ToolbarItem {
                    Button {
                        isPresented = false
                    } label: {
                        Text("Back")
                    }
                }
            }
            TestList()
            TestList()
        }
        .navigationViewStyle(.columns)
    }
}

Видео с использованием этого примера кода https://youtu.be/GAiRL8TprrM

0 ответов

Другие вопросы по тегам