You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何从自定义时间选择器获取计算值?

解决SwiftUI多滚轮时间选择器的@Binding同步问题

问题现状

你已经实现了多滚轮时间选择器,内部通过selectedTimeAsString计算属性生成选中的时间字符串,但无法让父视图获取到这个值。虽然声明了@Binding var time: String,但未将计算属性的结果同步到该绑定变量中。

简洁解决方案

无需额外创建模型,只需监听滚轮数字的变化,自动将计算出的时间字符串同步到@Binding变量即可,具体步骤如下:

  1. 添加数字变化监听
    在HoursPickerView的body中,给HStack添加.onChange修饰器,监听所有滚轮数字的变化,一旦有变动就更新time绑定变量:
struct HoursPickerView: View {

    @State private var hoursFirstDigit = 0
    @State private var hoursSecondDigit = 0
    @State private var hoursThirdDigit = 0
    @State private var hoursForthDigit = 0
    @State private var hoursLastDigit = 0

    @State private var minutesFirstDigit = 0
    @State private var minutesLastDigit = 0

    @Binding var time : String


    private var selectedTimeAsString : String {
        let hours = [hoursFirstDigit,hoursSecondDigit,hoursThirdDigit,hoursForthDigit,hoursLastDigit].map{"\($0)"}
        let minutes = [minutesFirstDigit,minutesLastDigit].map{"\($0)"}
        
        let hoursJoined = hours.joined()
        let minutesJoined = minutes.joined()
        
        return hoursJoined + ":" + minutesJoined
    }


    var body: some View {
        VStack {
            HStack(spacing : -15){
                HoursPickerColumn(range: 0...9, selection: $hoursFirstDigit)
                HoursPickerColumn(range: 0...9, selection: $hoursSecondDigit)
                HoursPickerColumn(range: 0...9, selection: $hoursThirdDigit)
                HoursPickerColumn(range: 0...9, selection: $hoursForthDigit)
                HoursPickerColumn(range: 0...9, selection: $hoursLastDigit)
                
                Text(":")
                    .font(.title)
                    .padding(.horizontal)
                
                HoursPickerColumn(range: 0...5, selection: $minutesFirstDigit)
                HoursPickerColumn(range: 0...9, selection: $minutesLastDigit)
                
            }
            .frame(width: 280, height: 50)
            .clipped()
            .background(
                RoundedRectangle(cornerRadius: 10)
                    .foregroundStyle(.white.shadow(.inner(color: .gray, radius: 1)))
            )
            // 监听所有滚轮数字变化,同步更新绑定的time变量
            .onChange(of: [hoursFirstDigit, hoursSecondDigit, hoursThirdDigit, hoursForthDigit, hoursLastDigit, minutesFirstDigit, minutesLastDigit]) { _ in
                time = selectedTimeAsString
            }
            
            Text(selectedTimeAsString).bold()
        }
    }
}
  1. 父视图使用方式
    在父视图中声明@State变量存储时间,绑定到HoursPickerView的time参数,即可实时获取选中的时间字符串:
struct ParentView: View {
    @State private var selectedTime = "00000:00"
    
    var body: some View {
        VStack {
            HoursPickerView(time: $selectedTime)
            Text("父视图获取的时间:\(selectedTime)")
        }
    }
}

可选优化:初始化同步初始时间

如果需要让滚轮初始化时显示父视图传入的初始时间,可添加初始化方法,将time字符串拆分到各个digit变量中:

init(time: Binding<String>) {
    self._time = time
    // 解析初始时间字符串,设置各个digit的初始值
    let components = time.wrappedValue.split(separator: ":")
    if let hoursStr = components.first, hoursStr.count == 5 {
        hoursFirstDigit = Int(String(hoursStr[hoursStr.startIndex])) ?? 0
        hoursSecondDigit = Int(String(hoursStr[hoursStr.index(after: hoursStr.startIndex)])) ?? 0
        hoursThirdDigit = Int(String(hoursStr[hoursStr.index(hoursStr.startIndex, offsetBy: 2)])) ?? 0
        hoursForthDigit = Int(String(hoursStr[hoursStr.index(hoursStr.startIndex, offsetBy: 3)])) ?? 0
        hoursLastDigit = Int(String(hoursStr[hoursStr.index(hoursStr.startIndex, offsetBy: 4)])) ?? 0
    }
    if let minutesStr = components.last, minutesStr.count == 2 {
        minutesFirstDigit = Int(String(minutesStr[minutesStr.startIndex])) ?? 0
        minutesLastDigit = Int(String(minutesStr[minutesStr.index(after: minutesStr.startIndex)])) ?? 0
    }
}

内容的提问来源于stack exchange,提问作者OverD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 23:47:24