有没有办法使用 SwiftUI 将选项绑定到切换/滑块

Lud*_*dry 4 iphone user-interface ios swift swiftui

我的数据模型中有一个UInt?(可选)属性,我试图将其绑定到ToggleSliderSwiftUI。我正在尝试实现这样的目标:

  • maximumRingsShownCount值为 4(不是 nil),那么开关应该打开并且该值绑定到滑块。
  • maximumExpandedRingsShownCount值为 nil,则切换应关闭并且不显示滑块。

使用 SwiftUI 渲染的切换和滑块

我在这里面临两个问题:

  1. 看起来我们不能有可选的绑定(对于滑块)
  2. 是否可以有一个转换器将可选值转换为布尔值(用于切换)?

到目前为止,在我看来,除了我的模型之外,我还声明了 2 个属性:

@ObjectBinding var configuration: SunburstConfiguration

@State private var haveMaximumRingsShownCount: Bool = false
@State private var haveMaximumExpandedRingsShownCount: Bool = false
Run Code Online (Sandbox Code Playgroud)

我的视图正文包含(对于每个属性):

Toggle(isOn: $haveMaximumRingsShownCount) {
    Text("maximumRingsShownCount")
}
if haveMaximumRingsShownCount {
    VStack(alignment: .leading) {
        Text("maximumRingsShownCount = \(config.maximumRingsShownCount!)")
            Slider(value: .constant(4 /* no binding here :( */ ))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

UI 布局是正确的,但我仍然遇到上述问题,因为:

  1. 状态haveMaximumRingsShownCount不受我的config.maximumRingsShownCount模型是否为零的约束
  2. 滑块当前仅显示一个常量,未绑定到展开的config.maximumRingsShownCount属性

关于如何使用选项解决这些问题有什么想法吗?

[这可以在https://github.com/lludo/SwiftSunburstDiagram的示例代码中重现]

小智 5

我发现重载 nil 合并运算符 (??) 来处理这种情况很方便。

// OptionalBinding.swift

import Foundation
import SwiftUI

func OptionalBinding<T>(_ binding: Binding<T?>, _ defaultValue: T) -> Binding<T> {
    return Binding<T>(get: {
        return binding.wrappedValue ?? defaultValue
    }, set: {
        binding.wrappedValue = $0
    })
}

func ??<T> (left: Binding<T?>, right: T) -> Binding<T> {
    return OptionalBinding(left, right)
}

Run Code Online (Sandbox Code Playgroud)

然后您可以按如下方式使用它:

struct OptionalSlider: View {
    @Binding var optionalDouble: Double?

    var body: some View {
        Slider(value: $optionalDouble ?? 0.0, in: 0.0...1.0)
    }
}
Run Code Online (Sandbox Code Playgroud)