Боковая панель SwiftUI не запоминает состояние

У меня есть это приложение, в котором используется новая боковая панель, представленная в iOS14 для iPad, но я не могу понять, почему оно не запоминает состояние, когда оно скрыто

Это структура боковой панели

import SwiftUI

struct Sidebar: View {
    
    @Environment(\.managedObjectContext) var moc
    @Binding var selection : Set<NavigationItem>
    
    var body: some View {
        List(selection: $selection) {
            NavigationLink(destination: AgendaView().environment(\.managedObjectContext, moc).navigationTitle("Agenda"), label: {
                Label("Agenda", systemImage: "book")
            })
            .tag(NavigationItem.agenda)
            
            NavigationLink(destination: Text("Subjects"), label: {
                Label("Materie", systemImage: "tray.full")
            })
            .tag(NavigationItem.subjects)
            
            NavigationLink(destination: Text("Calendario"), label: {
                Label("Calendario", systemImage: "calendar")
            })
            .tag(NavigationItem.calendar)
            
            NavigationLink(destination: SettingsView().environment(\.managedObjectContext, moc).navigationTitle("Impostazioni"), label: {
                Label("Impostazioni", systemImage: "gear")
            })
            .tag(NavigationItem.settings)
            
        }
        .listStyle(SidebarListStyle())
    }
}

для маркировки элементов я использую настраиваемую структуру под названием NavigationItem

enum NavigationItem {
    case agenda
    case calendar
    case ...
}

и здесь я разместил боковую панель в представлении содержимого, поскольку вы можете видеть, является ли устройство iPad (обнаруженным с помощью sizeClasses), я использую боковую панель, в противном случае, если это iPhone, я использую TabBar

import SwiftUI

struct ContentView: View {
    @Environment(\.horizontalSizeClass) var horizontalSizeClass
    @Environment(\.managedObjectContext) var moc
    
    @State private var selection : Set<NavigationItem> = [.agenda]
    
    @ViewBuilder
    var body: some View {
        
        if horizontalSizeClass == .compact {
            TabBar(selection: $selection)
                .environment(\.managedObjectContext, moc)
        } else {
            NavigationView {
                Sidebar(selection: $selection)
                    .environment(\.managedObjectContext, moc)
                    .navigationTitle("Menu")
            }
        }
    }
}

person Luca    schedule 06.07.2020    source источник
comment
Пробные проекты Apple WWDC также страдают от ошибки. Я подал радар, и тебе, наверное, тоже стоит. Но обходной путь для преобразования боковой панели в TabView был бы отличным.   -  person jlsiewert    schedule 09.07.2020
comment
Да, я видел, что в приложении Fruta есть такая же ошибка, я надеюсь, что это скоро исправят, если яблоко увидит, что это ошибка   -  person Luca    schedule 09.07.2020
comment
Кстати, как установить то, что выбрано по умолчанию? Я использую версию боковой панели по умолчанию, и в исходном состоянии ничего не выбрано.   -  person Ryan    schedule 13.07.2020
comment
Для элемента, выбранного по умолчанию, я использую настраиваемый Enum с именем NavigationItem, как вы можете видеть из моего кода @State private var section ... и я сделал его копирующим приложение Apple WWDC20 Fruta, которое также делает это, чтобы установить состояние боковой панели по умолчанию, однако это не работает, потому что, когда я запускаю приложение, ничего не выбрано, надеюсь, Apple исправит это!   -  person Luca    schedule 13.07.2020


Ответы (2)


List(selection: $selection) для привязки выбора - только macOS. Смотрите этот комментарий в шапке:

/// On iOS and tvOS, you must explicitly put the list into edit mode for
/// the selection to apply.

В качестве обходного пути вы можете выделить ранее выбранную строку жирным шрифтом, например

 NavigationLink(
        destination: HomeView(),
        tag: Screen.home,
        selection: $selection,
        label: {
            Label("Home", systemImage: "house" )
        })
        .font(Font.headline.weight(selection == Screen.home ? .bold : .regular))

Подробнее см. В этом ответе.

person malhal    schedule 26.10.2020

Если вам не нужно выбирать несколько строк на боковой панели, измените определение selection на:

@Binding var selection: NavigationItem?

Предупреждение: если вы хотите использовать ту же переменную selection для TabView, это не сработает. Вам нужно будет определить другое свойство как NavigationItem, которое не является необязательным.

person Lewis Godowski    schedule 25.05.2021