Можно ли иметь два разных типа объектов в списке выбора SwiftUI?

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

struct ProjectView: View
{
    @State private var readers: [Reader]
    @State private var selectedReader: Reader?
    
    init(readers: [Reader])
    {
        self.readers = readers
    }
    
    var body: some View
    {
        NavigationSplitView
        {
                List(selection: self.$selectedReader)
                {
                    Button("Book")
                    {
                        self.selectedReader = nil
                    }
                    
                    Divider()
                                        
                    ForEach (self.readers, id: \.self)
                    {
                        reader in Text(reader.name)
                    }
                }
        }
        detail:
        {
            if let selectedReader = self.selectedReader
            {
                ReaderView(reader: selectedReader)
            }
            else
            {
                BookView()
            }
        }
        #if os(macOS)
        .navigationSplitViewColumnWidth(min: 180, ideal: 200)
        #endif
        .navigationTitle(self.project.name)
    }
}

Я пытаюсь сделать так, чтобы "Книга" выделялась/подсвечивалась так же, как и имена читателей в списке читателей, вы можете увидеть, что я имею в виду в этом видео:

https://youtube.com/shorts/__IA890FxG0?feature=share

Кто-нибудь знает, как это сделать? Или это вообще возможно?

Обратите внимание: вы не должны инициализировать self.readers = readers, это должно быть _readers = State(initialValue: readers) или использовать let readers: [Reader]. Если вам нужно сменить читателя, используйте @Binding. Также не стоит использовать ForEach (self.readers, id: \.self), сделайте структуру Reader Identifiable. Как вы заявляете selectedReader? Обратите внимание: Above the list of readers is a home button "Book" ... нет, кнопка находится вверху списка, а не над ним.

workingdog support Ukraine 25.07.2024 03:04

@workingdogsupportUkraine Спасибо за советы. Забыл добавить объявление для selectedReader, поменял.

Ser Pounce 25.07.2024 04:06
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Следует использовать ReaderOrBook?, так как выбором может быть либо читалка, либо «Книга», либо вообще ничего не выбрано (nil).

enum ReaderOrBook: Hashable {
    case book
    case reader(Reader)
    
    // convenient property to convert a ReaderOrBook to a Reader 
    var asReader: Reader? {
        if case let .reader(r) = self {
            return r
        }
        return nil
    }
}

Тогда вам просто нужно tag правильно расположить строки списка.

struct ProjectView: View {
    // this should not be a @State since you want callers to pass in an array of readers
    // if you want to mutate this in ProjectView, make it a @Binding instead
    let readers: [Reader]
    @State private var selectedReaderOrBook: ReaderOrBook?
    
    var body: some View {
        NavigationSplitView {
            List(selection: self.$selectedReaderOrBook) {
                Text("Book").tag(ReaderOrBook.book)
                
                Divider()
                
                ForEach (self.readers, id: \.self) { reader in
                    Text(reader.name)
                        .tag(ReaderOrBook.reader(reader))
                }
            }
        } detail: {
            // ...
        }
    }
}

Ух ты, это такое замечательное решение, я только что реализовал его, и оно работало отлично. Большое спасибо!

Ser Pounce 25.07.2024 05:34

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