Сохраните выбор списка SwiftUI с помощью @AppStorage в приложении для Mac

#swift #macos #swiftui

Вопрос:

В приложении для Mac я пытаюсь сохранить выбор списка SwiftUI с помощью AppStorage. Цель состоит в том, чтобы приложение запомнило последний выбор таким образом, чтобы он был выбран при перезапуске приложения. Я не могу понять, как привязать выделение к свойству AppStorage. Есть какие-нибудь предложения о том, как этого добиться?

 enum Fruit: String, CaseIterable, Identifiable {
    case apple
    case orange
    case mango
    case lemon
    var id: String { rawValue }
}

struct Sidebar: View {

    @Binding var selection: Fruit

    var body: some View {
        List(Fruit.allCases, id: .self, selection: $selection) { fruit in
            Text(fruit.rawValue)
        }
        .listStyle(SidebarListStyle())
        .frame(minWidth: 150)
    }
}

struct DetailView: View {

    var selection: Fruit

    var body: some View {
        switch selection {
        case .apple:
            Text("🍎 (selection.rawValue)").font(.title).frame(minWidth: 200)
        case .orange:
            Text("🍊 (selection.rawValue)").font(.title).frame(minWidth: 200)
        case .mango:
            Text("🥭 (selection.rawValue)").font(.title).frame(minWidth: 200)
        case .lemon:
            Text("🍋 (selection.rawValue)").font(.title).frame(minWidth: 200)
        }
    }
}

struct ContentView: View {
    
    @AppStorage("selection") private var selection: Fruit = .apple

    var body: some View {
        NavigationView {
            Sidebar(selection: $selection)
            DetailView(selection: selection)
        }
        .frame(width: 500, height: 300)
    }
}
 

Комментарии:

1. Попробуйте выбрать onTapGesture = фрукты в виде боковой панели . Я почти уверен, что вы не можете использовать выбор списка, как вы используете выбор выбора.

2. Вы можете поместить необязательный выбор в a List . См. Список . Однако список не принимает прямую @AppStorage в качестве прямой привязки. Ваш способ-это простое решение этой проблемы…

Ответ №1:

Используйте пользовательскую привязку при выборе.

 struct Sidebar: View {
    
    @Binding var selection: Fruit

    var body: some View {
        List(Fruit.allCases, id: .self, selection: Binding($selection)) { fruit in
            Text(fruit.rawValue)
        }
        .listStyle(SidebarListStyle())
        .frame(minWidth: 150)
    }
}
 

или

 List(Fruit.allCases, id: .self, selection: Binding(get: {selection}, set: {selection = $0 ?? Fruit.apple}$selection)) {
 

Комментарии:

1. Почему бы не использовать Binding($selection) ?

2. @шевеление, да. Это альтернатива. Но ты правильно понял идею?

3. Можете ли вы добавить к своему ответу Binding($selection) подход? Просто чтобы другие знали об этом.

4. Я имел в виду, что в своем ответе вы показываете оба подхода. Таким образом, люди знают об обоих способах решения проблемы. Поэтому, пожалуйста, также покажите свой оригинальный ответ.

Ответ №2:

В вашем нет ничего плохого Binding . Вам просто нужен способ выбора различных фруктов:

     List(Fruit.allCases, id: .self) { fruit in
        Text(fruit.rawValue)
            .onTapGesture {
                selection = fruit
            }
    }
 

В противном случае он отлично работает с тем, что вы закодировали.

Я не уверен, как у вас это не получается, но вот видео: Запись экрана 2021-10-04 в 11.10.29 утра(720)

Комментарии:

1. Это не работает. Он удаляет $selection привязку из списка, поэтому выбранный элемент не обновляется.

2. Он был протестирован на Xcode 13RC и macOS 11.6.

3. Я также использовал Xcode 13 на macOS 11.6, но выбор списка не работает. Если нет List(selection:) , то как вы обновляете состояние списка? В вашем примере selection обновляется привязка для представления, а не для списка.

4. Обновлено видео, показывающее, что оно работает.

5. В вашем видео элементы боковой панели не выделяются при выборе элемента, поскольку состояние выбора в списке не обновляется. Вот изображение рабочего примера pasteboard.co/pJsuXvA8Sgop.png