我创建了一个用户界面来控制灯光,包括一个亮度滑块。它几乎按预期工作。但是现在我添加了用于将亮度提高/降低 10% 的按钮。它的工作原理是灯光相应变暗,状态也会更新并调用 body 方法,并且正如 LightsCell 正文中的打印输出所显示的那样,使用正确的值调用它,但不会相应地更新滑块。< /p>
我错过了什么?谢谢
完整代码:https://gitlab.com/vikingosegundo/brighter-hue
import SwiftUI
final class ViewState: ObservableObject {
@Published var lights : [ Light ] = []
@Published var rooms : [ Room ] = []
init(store: Store) {
store.updated { self.process(state(of: store)) }
process(state(of: store))
}
func handle(msg: Message) { }
private func process(_ appState: AppState) {
DispatchQueue.main.async {
self.lights = appState.lights.sorted(on:\.name, by:<)
self.rooms = appState.rooms.sorted(on:\.title, by:<)
}
}
}
struct ContentView: View {
init(viewState: ViewState, rootHandler: @escaping (Message) -> ()) {
self.viewState = viewState
self.rootHandler = rootHandler
}
@ObservedObject private var viewState: ViewState
private let rootHandler: (Message) -> ()
var body: some View {
TabView {
Dashboard(rootHandler)
Lights (rootHandler)
Rooms (rootHandler)
Shop (rootHandler)
Settings (rootHandler)
}.environmentObject(viewState)
}
}
struct Lights: View {
init(_ rootHandler: @escaping (Message) -> ()) {
self.rootHandler = rootHandler
}
@EnvironmentObject
private var viewState: ViewState
private let rootHandler: (Message) -> ()
var body: some View {
VStack {
NavigationView {
List {
ForEach(viewState.lights) { LightCell(light: $0, rootHandler:rootHandler) }
}.buttonStyle(PlainButtonStyle()).navigationTitle("Lights")
}
}.tabItem {
Label("Lights", systemImage: "lightbulb")
}
}
}
struct LightCell: View {
init(light: Light, rootHandler: @escaping (Message) -> ()) {
self.rootHandler = rootHandler
self.light = light
self.isOn = light.isOn
self.hue = light.hue
self.sat = light.saturation
self.bri = light.brightness
self.ct = Double(-light.ct)
}
var body: some View {
print("\(light.name) \(light.id): \(light.brightness)")
return VStack {
HStack {
Text("\(light.name)").bold().dynamicTypeSize(.xLarge).fixedSize()
Spacer()
Toggle("", isOn: $isOn)
.onChange(of: isOn) { _ in
switch (light.isOn, isOn) {
case (true, false): rootHandler(.lighting(.turn(light,.off)))
case (false, true): rootHandler(.lighting(.turn(light,.on )))
case ( _ , _ ): ()
}
}
}
HStack {
Spacer()
Picker("", selection: $_displayStyle) {
Image(systemName: "thermometer").tag(0)
Image(systemName: "paintpalette").tag(1)
}.pickerStyle(.segmented).fixedSize()
Spacer()
}
LazyVGrid(columns: [GridItem(.fixed(80)), GridItem(.flexible())], alignment: .trailing) {
switch displayStyle(for: _displayStyle) {
case .hsb:
Text("Hue" ).dynamicTypeSize(.xSmall); Slider(value: $hue) { _ in rootHandler( .lighting(.set(.values(.hsb(hue,sat,bri), on:light))) ) }
Text("Saturation").dynamicTypeSize(.xSmall); Slider(value: $sat) { _ in rootHandler( .lighting(.set(.values(.hsb(hue,sat,bri), on:light))) ) }
case .ct:
Text("Color Temp").dynamicTypeSize(.xSmall).minimumScaleFactor(0.5); Slider(value: $ct, in: (-500)...(-153)) { _ in rootHandler( .lighting(.set(.values(.ct(Int(-ct),bri), on:light))) ) }
}
Text("Brightness").dynamicTypeSize(.xSmall); HStack {
Button("-") { rootHandler( .lighting( .decrease(.brightness, by:.percent(10), on:light )) ) }
Slider(value: $bri) { _ in rootHandler( .lighting( .set(.values(.bri(bri), on:light))) ) }
Button("+") { rootHandler( .lighting( .increase(.brightness, by:.percent(10), on:light )) ) }
}
}
}
}
private let light : Light
private let rootHandler: (Message) -> ()
@State private var isOn : Bool
@State private var hue : Double
@State private var sat : Double
@State private var bri : Double
@State private var ct : Double
@State private var _displayStyle: Int = 0
}
extension LightCell {
fileprivate enum DisplayStyle: Int, Hashable {
case hsb
case ct
}
private func selected(_ style: DisplayStyle) {
_displayStyle = number(for: style)
print("\(style) selected for \(light.name)")
}
}
private
func displayStyle(for x:Int) -> LightCell.DisplayStyle {
switch x {
case 0: return .ct
case 1: return .hsb
default: return .ct
}
}
private
func number(for x:LightCell.DisplayStyle) -> Int {
switch x {
case .ct : return 0
case .hsb: return 1
}
}
答案 0 :(得分:1)
您还需要在点击按钮时更新 $bri
var。
您需要这个,因为滑块和按钮之间没有关系/联系。
Text("Brightness"); HStack {
Button("-") {
rootHandler( .lighting( .decrease(.brightness, by:.percent(10), on:light )) )
bri = light.brightness //<-- Here
}
Slider(value: $bri) { _ in rootHandler( .lighting( .set(.values(.bri(bri), on:light))) ) }
Button("+") {
rootHandler( .lighting( .increase(.brightness, by:.percent(10), on:light )) )
bri = light.brightness //<-- Here
}
}
或者你也可以使用这个
Text("Brightness"); HStack {
// HStack Code
}
.onChange(of: light.brightness, perform: { value in
bri = value //<-- Here
})
注意:我删除了额外的代码,因为我使用的是旧的 Xcode。