enum SectionType: String, CaseIterable {
case top = "Top"
case best = "Best"
}
struct ContentView : View {
@State private var selection: Int = 0
var body: some View {
SegmentedControl(selection: $selection) {
ForEach(SectionType.allCases.identified(by: \.self)) { type in
Text(type.rawValue).tag(type)
}
}
}
}
Comment exécuter du code (par exemple print("Selection changed to \(selection)")
lorsque l'état $selection
Change? J'ai parcouru les documents et je n'ai rien trouvé.
Vous ne pouvez pas utiliser didSet
observer sur @State
mais vous pouvez le faire sur une propriété ObservableObject
.
import SwiftUI
import Combine
final class SelectionStore: ObservableObject {
var selection: SectionType = .top {
didSet {
print("Selection changed to \(selection)")
}
}
// @Published var items = ["Jane Doe", "John Doe", "Bob"]
}
Ensuite, utilisez-le comme ceci:
import SwiftUI
enum SectionType: String, CaseIterable {
case top = "Top"
case best = "Best"
}
struct ContentView : View {
@ObservedObject var store = SelectionStore()
var body: some View {
List {
Picker("Selection", selection: $store.selection) {
ForEach(FeedType.allCases, id: \.self) { type in
Text(type.rawValue).tag(type)
}
}.pickerStyle(SegmentedPickerStyle())
// ForEach(store.items) { item in
// Text(item)
// }
}
}
}
Voici une autre option si vous avez un composant qui met à jour un @Binding
. Plutôt que de faire cela:
Component(selectedValue: self.$item, ...)
vous pouvez le faire et avoir un peu plus de contrôle:
Component(selectedValue: Binding(
get: { self.item },
set: { (newValue) in
self.item = newValue
// now do whatever you need to do once this has changed
}), ... )
De cette façon, vous obtenez les avantages de la liaison ainsi que la détection du moment où le Component
a changé la valeur.
Ne répondant pas vraiment à votre question, mais voici la bonne façon de configurer SegmentedControl
(je ne voulais pas publier ce code en tant que commentaire, car il a l'air moche). Remplacez votre version ForEach
par le code suivant:
ForEach(0..<SectionType.allCases.count) { index in
Text(SectionType.allCases[index].rawValue).tag(index)
}
Le balisage des vues avec des cas d'énumération ou même des chaînes fait qu'il se comporte de manière inadéquate - la sélection ne fonctionne pas.
Vous pouvez également ajouter les éléments suivants après la déclaration SegmentedControl
pour vous assurer que la sélection fonctionne:
Text("Value: \(SectionType.allCases[self.selection].rawValue)")
Version complète de body
:
var body: some View {
VStack {
SegmentedControl(selection: self.selection) {
ForEach(0..<SectionType.allCases.count) { index in
Text(SectionType.allCases[index].rawValue).tag(index)
}
}
Text("Value: \(SectionType.allCases[self.selection].rawValue)")
}
}
Concernant votre question - j'ai essayé d'ajouter didSet
observateur à selection
, mais cela plante l'éditeur Xcode et génère une erreur "Segmentation fault: 11" lors de la construction.