SwiftUI: выберите NavigationLink в NavigationView / List с помощью SidebarListStyle - PullRequest
2 голосов
/ 03 августа 2020

Я хочу программно выбрать конкретный c NavigationLink в NavigationView / List.

Следующий код отлично работает на iPhone как в портретном, так и в ландшафтном режиме == в ситуациях, когда Список не отображается постоянно, кроме его целевого вида.

введите описание изображения здесь

Код:

struct ContentView: View {

private let listItems = [ListItem(), ListItem(), ListItem()]
@State var selection: Int? = 0

var body: some View {
    NavigationView {
        
        List(listItems.indices) {
            index in
            
            let item = listItems[index]
            let isSelected = (selection ?? -1) == index
            
            NavigationLink(destination: Text("Destination \(index)"),
                           tag: index,
                           selection: $selection) {
                
                Text("\(item.name) \(index) \(isSelected ? "selected" : "")")
                
            }
            
        }
    
    }
    .listStyle(SidebarListStyle())
    .onAppear(perform: {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
            selection = 2
        })
    })
    }

}


struct ListItem: Identifiable {
    var id = UUID()
    var name: String = "Some Item"
}

Но он не работает на iPad в ландшафтном режиме: хотя сама навигация работает (пункт назначения отображается правильно), NavigationLink остается невыделенным .

→ Как выбрать ссылку NavigationLink так, чтобы она отображалась выбранной и на iPad?

1 Ответ

1 голос
/ 03 августа 2020

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

Протестировано с Xcode 12b3 / iOS + iPadOS 14.

class SelectionViewModel: ObservableObject {
    var currentRow: Int = -1 {
        didSet {
            self.selection = currentRow
        }
    }

    @Published var selection: Int? = nil
}

struct SidebarContentView: View {
@StateObject var vm = SelectionViewModel()
private let listItems = [ListItem(), ListItem(), ListItem()]

var body: some View {
    NavigationView {

        List(listItems.indices) {
            index in

            let item = listItems[index]
            let isSelected = vm.currentRow == index

            Button("\(item.name) \(index) \(isSelected ? "selected" : "")") { vm.currentRow = index }
            .background (
                NavigationLink(destination: Text("Destination \(index) selected: \(vm.currentRow)"),
                               tag: index,
                               selection: $vm.selection) {
                    EmptyView()
                }.hidden()
            )
        }

    }
    .listStyle(SidebarListStyle())
    .onAppear(perform: {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
            vm.currentRow = 2
        })
    })
    }
}
...