Проблема SwiftUI NavigationView со сценарием «Родитель-потомок-внук» при попытке предыдущей следующей навигации внука

#swiftui #parent-child #navigationview #swiftui-navigationlink #swiftui-navigationview

#swiftui #родитель-потомок #navigationview #swiftui-navigationlink #swiftui-navigationview

Вопрос:

Я использую SwiftUI в проекте, для которого требуется модель со структурой сущностей «один ко многим ко многим». Я использую навигационное представление на родительском уровне с навигационными ссылками на родительском и дочернем уровнях.

Это хорошо работает в том смысле, что я могу:

  1. Выберите дочерний элемент на родительском уровне, чтобы перейти к дочернему элементу
  2. Выберите внука на дочернем уровне, чтобы перейти к внуку

У меня есть дополнительное требование — предоставить кнопки next и previous на уровне внука. Я делаю это, используя функцию тегов / выбора, предусмотренную для ссылок навигации. Я присваиваю каждому внуку числовой индексный тег, а затем вызываю переданные функции на дочернем уровне, чтобы изменить выбранный дочерний вид, добавив или вычтя его из индекса.

Проблема в том, что когда я перехожу к следующему или предыдущему внуку, ссылка «назад» изменяется на либо на последнего посещенного внука, либо на слово «Назад» вместо дочернего представления. Если я затем выберу ссылку «назад» в этом представлении, произойдет немедленный переход к ранее посещенному внуку, за которым последует немедленный переход к дочернему представлению.

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

Если я изменю код на более простую родительскую дочернюю модель со следующими и предыдущими на дочернем уровне, все это работает так, как ожидалось, поэтому проблема связана с тремя уровнями. Любая помощь с решением будет очень приветствоваться.

 //
//  ContentView.swift
//  NextPreviousTest
//
//  Created by Mike Cooper on 26/09/2020.
//
import SwiftUI

struct ContentView: View {
    
    var body: some View {
        NavigationView {
            VStack {
                Spacer()
                NavigationLink(destination: ChildView()) {
                    Text("Child View")
                }.buttonStyle(PlainButtonStyle())
                Spacer()
            }.navigationBarTitle(Text("Parent"), displayMode: .inline)
        }
    }
        
}

struct ChildView: View {
    @State private var array = [0, 1, 2, 3, 4, 5]
    @State private var selectedGrandChild: String? = nil
    
    var body: some View {
        ScrollView {
            ForEach(0..<array.count) { i in
                NavigationLink(destination: GrandChildView(viewIndex: self.array[i], prevFunction: childView_prevFunction,
                                                      nextFunction: childView_nextFunction
                )
                , tag: String(self.array[i]), selection: $selectedGrandChild) {
                    Text("Grandchild (self.array[i])").padding()
                }.buttonStyle(PlainButtonStyle())
            }
        }.navigationBarTitle(Text("Child"), displayMode: .inline)
    }
    
    private func childView_prevFunction() {
        let tag = Int(self.selectedGrandChild ?? "0")
        if tag! > 0 {
            self.selectedGrandChild = String(tag! - 1)
            print(String(tag! - 1))
        }
    }
    
    private func childView_nextFunction() {
        let tag = Int(self.selectedGrandChild ?? "0")
        if tag! < self.array.count - 1 {
            self.selectedGrandChild = String(tag!   1)
            print(String(tag!   1))
        }
    }
    
}

struct GrandChildView: View {
    
    let viewIndex: Int
    var prevFunction: () -> Void
    var nextFunction: () -> Void
    
    var body: some View {
        VStack{
            HStack {
                Button(action: {
                    self.prevFunction()
                }) {
                    Image(systemName: "chevron.left")
                }
                Text("Grandchild (viewIndex)")
                Button(action: {
                    self.nextFunction()
                }) {
                    Image(systemName: "chevron.right")
                }
            }.font(.headline)
        }.navigationBarTitle("Grandchild (viewIndex)").font(.caption)
    }
}