使用需要强制转换的自定义绑定时,滑块(绑定值)可能不会更新(SwiftUI)

kyks70gy  于 2023-01-12  发布在  Swift
关注(0)|答案(1)|浏览(117)

在我向你们展示之前,我想先解释一下我的问题。我有一个SettingsViewModel,它保存了一个协议类型为Settings的变量。我用一些SpecificSetting初始化了这个变量。在我的SettingsView中,我有一个SpecificSettingsView,如果我有SpecificSettings的话,它是可见的。因为我需要强制转换它,并且不需要一个可选的,我需要一个自定义绑定来传递给我的子视图,这允许修改设置。编辑是通过2个滑块完成的,如果我编辑someValuesomeOtherValue应该增加someValue + 5。但特别是如果我快速拖动滑块,这是不正确的。
下面是代码,如果你想检查出来:协议和型号:

protocol Settings {}
struct SpecificSettings: Settings {
    var someValue: Double
    var someOtherValue: Double
}

视图模型:

class SettingsViewModel: ObservableObject {
    // Can be initialized with any value
    @Published var settings: Settings = SpecificSettings(someValue: 5, someOtherValue: 10)
    
    // I dont have this property in my actual code
    @Published var specificSettings = SpecificSettings(someValue: 5, someOtherValue: 10)
}

设置视图:我还添加了一个可以工作的代码片段。如果不将设置强制转换为SpecificSetting,它就可以工作。但我不能在我的实际代码库中这样做。

struct SettingsView: View {
    @StateObject private var viewModel = SettingsViewModel()
    
    var body: some View {
        VStack {
            if let specificSettings = viewModel.settings as? SpecificSettings {
                let specificSettingBinding = Binding {
                    specificSettings
                } set: { newSpecificSettings, _ in
                    viewModel.settings = newSpecificSettings
                }
                // cast settings and pass a custom binding -> does not work
                SpecificSettingsView(specificSettings: specificSettingBinding)
            }
            Divider()
                .padding(30)
            // directly pass specific settings without custom binding and casting -> Works
            SpecificSettingsView(specificSettings: $viewModel.specificSettings)
        }
        .padding()
    }
}

特定设置的编辑视图:

struct SpecificSettingsView: View {
    @Binding var specificSettings: SpecificSettings
    
    var body: some View {
        VStack {
            Text(specificSettings.someValue.description)
            Slider(value: $specificSettings.someValue,
                   in: 0 ... 100)
            
            Text(specificSettings.someOtherValue.description)
            Slider(value: $specificSettings.someOtherValue,
                   in: 0 ... 100)
        }
        .onChange(of: specificSettings.someValue) { newValue in
            specificSettings.someOtherValue = newValue + 5
        }
    }
}

您可能已经在预览中遇到该问题:

struct SettingsView_Previews: PreviewProvider {
    static var previews: some View {
        SettingsView()
    }
}
2hh7jdfx

2hh7jdfx1#

我通过修改SpecificSettingsView修复了这个问题,我使用了第二个自定义绑定来代替onChange()修饰符在setter中进行调整:

struct SpecificSettingsView: View {
    @Binding var specificSettings: SpecificSettings

    private var customBinding: Binding<SpecificSettings> {
        Binding {
            specificSettings
        } set: { newSettings in
            var newSettings = newSettings
            newSettings.someOtherValue = newValue + 5
            specificSettings = newSettings
        }
    }
            
    
    var body: some View {
        VStack {
            Text(specificSettings.someValue.description)
            Slider(value: customBinding.someValue,
                   in: 0 ... 100)
            
            Text(specificSettings.someOtherValue.description)
            Slider(value: customBinding.someOtherValue,
                   in: 0 ... 100)
        }
    }
}

相关问题