J'expérimente avec SwiftUI et le contrôle Slider comme ceci:
struct MyView: View {
@State private var value = 0.5
var body: some View {
Slider(value: $value) { pressed in
}
}
}
J'essaie d'obtenir des mises à jour continues de Slider
au fur et à mesure que l'utilisateur le fait glisser, mais il semble qu'il ne met à jour la valeur qu'à la fin du changement de valeur.
Quelqu'un a joué avec ça? savoir comment obtenir un curseur SwiftUI pour émettre un flux de modifications de valeur? Combinez peut-être?
Dans SwiftUI, vous pouvez lier des éléments d'interface utilisateur tels que le curseur aux propriétés de votre modèle de données et y implémenter votre logique métier.
Par exemple, pour obtenir des mises à jour continues du curseur:
import SwiftUI
import Combine
final class SliderData: BindableObject {
let didChange = PassthroughSubject<SliderData,Never>()
var sliderValue: Float = 0 {
willSet {
print(newValue)
didChange.send(self)
}
}
}
struct ContentView : View {
@EnvironmentObject var sliderData: SliderData
var body: some View {
Slider(value: $sliderData.sliderValue)
}
}
Notez que pour que votre scène utilise l'objet de modèle de données, vous devez mettre à jour votre window.rootViewController
à quelque chose comme ci-dessous dans la classe SceneDelegate, sinon l'application se bloque.
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(SliderData()))
Après avoir beaucoup joué, je me suis retrouvé avec le code suivant. C'est un peu réduit pour garder la réponse courte, mais voilà. Il y avait quelques choses dont j'avais besoin:
struct AspectSlider: View {
// The first part of the hint text localization key.
private let hintKey: String
// An external integer binding to be set when the rounded value of the slider
changes to a different integer.
private let value: Binding<Int>
// A local binding that is used to track the value of the slider.
@State var sliderValue: Double = 0.0
init(value: Binding<Int>, hintKey: String) {
self.value = value
self.hintKey = hintKey
}
var body: some View {
VStack(alignment: .trailing) {
// The localized text hint built from the hint key and the rounded slider value.
Text(LocalizedStringKey("\(hintKey).\(self.value.value)"))
HStack {
Text(LocalizedStringKey(self.hintKey))
Slider(value: Binding<Double>(
getValue: { self.$sliderValue.value },
setValue: { self.sliderChanged(toValue: $0) }
),
through: 4.0) { if !$0 { self.slideEnded() } }
}
}
}
private func slideEnded() {
print("Moving slider to nearest whole value")
self.sliderValue = self.sliderValue.rounded()
}
private func sliderChanged(toValue value: Double) {
$sliderValue.value = value
let roundedValue = Int(value.rounded())
if roundedValue == self.value.value {
return
}
print("Updating value")
self.value.value = roundedValue
}
}
Je ne parviens pas à reproduire ce problème sur iOS 13 Bêta 2. Quel système d'exploitation ciblez-vous?
À l'aide d'une reliure personnalisée, la valeur est imprimée pour chaque petite modification, non seulement une fois l'édition terminée.
Slider(value: Binding<Double>(getValue: {0}, setValue: {print($0)}))
Notez que la fermeture ({ pressed in }
) signale uniquement lorsque la modification de fin commence et se termine, le flux de valeurs est uniquement transmis à la liaison.
iOS 13.4, Swift 5.x
Une réponse basée sur Mohammid excellente solution, seulement je ne voulais pas utiliser de variables environnementales.
class SliderData: ObservableObject {
let didChange = PassthroughSubject<SliderData,Never>()
@Published var sliderValue: Double = 0 {
didSet {
print("sliderValue \(sliderValue)")
didChange.send(self)
}
}
}
@ObservedObject var sliderData:SliderData
Slider(value: $sliderData.sliderValue, in: 0...Double(self.textColors.count))
Avec une petite modification de ContentView_Preview et la même chose dans SceneDelegate.
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(sliderData: SliderData.init())
}
}