Swift 如何使用增量&;步进器中的减量功能,同时也使用onChange修饰符

Swift 如何使用增量&;步进器中的减量功能,同时也使用onChange修饰符,swift,swiftui,Swift,Swiftui,我已经有了音频播放器的设置 除了步进器的当前功能外,我还想为onIncrement和onDecrement播放单独的声音 此项目使用核心数据进行持久化$当数量更改时,EstimaterData.qty侦听已发布的var我的视图模型。新数量保存在我的视图模型EstimaterData.save()中 这里是到文档的链接 我正试图盘算一下,是否有一个初始值设定者符合我正在努力实现的目标 Stepper("", value: $estimatorData.qty.onChange

我已经有了音频播放器的设置

除了步进器的当前功能外,我还想为onIncrement和onDecrement播放单独的声音

此项目使用核心数据进行持久化$当数量更改时,EstimaterData.qty侦听已发布的var我的视图模型。新数量保存在我的视图模型EstimaterData.save()中

这里是到文档的链接

我正试图盘算一下,是否有一个初始值设定者符合我正在努力实现的目标

Stepper("", value: $estimatorData.qty.onChange { qty in
    estimatorData.save()
}, in: 0...10000)
    .frame(width: 100, height: 35)
    .offset(x: -4)
    .background(colorScheme == .dark ? Color.blue : Color.blue)
    .cornerRadius(8)
这是我的球员

func incrementTaped() {
    playSound(sound: "plus", type: "mp3")
}
 
func decrementTaped() {
    playSound(sound: "minus", type: "m4a")
}
问题 目前还没有一个组合了
onIncrement
/
ondescrement
函数和
/
边界
/
步骤
参数的初始化器

您可以有
onIncrement
onecrement

public init(onIncrement: (() -> Void)?, onDecrement: (() -> Void)?, onEditingChanged: @escaping (Bool) -> Void = { _ in }, @ViewBuilder label: () -> Label)
边界
步骤

public init<V>(value: Binding<V>, in bounds: ClosedRange<V>, step: V.Stride = 1, onEditingChanged: @escaping (Bool) -> Void = { _ in }, @ViewBuilder label: () -> Label) where V : Strideable
演示

struct ContentView: View {
    @State private var value = 1

    var body: some View {
        CustomStepper(value: $value, in: 1...10, onIncrement: onIncrement, onDecrement: onDecrement) {
            Text(String(value))
        }
        .onChange(of: value) {
            print("onChange value: \($0)")
        }
    }
    
    func onIncrement() {
        print("onIncrement")
    }

    func onDecrement() {
        print("onDecrement")
    }
}
问题 目前还没有一个组合了
onIncrement
/
ondescrement
函数和
/
边界
/
步骤
参数的初始化器

您可以有
onIncrement
onecrement

public init(onIncrement: (() -> Void)?, onDecrement: (() -> Void)?, onEditingChanged: @escaping (Bool) -> Void = { _ in }, @ViewBuilder label: () -> Label)
边界
步骤

public init<V>(value: Binding<V>, in bounds: ClosedRange<V>, step: V.Stride = 1, onEditingChanged: @escaping (Bool) -> Void = { _ in }, @ViewBuilder label: () -> Label) where V : Strideable
演示

struct ContentView: View {
    @State private var value = 1

    var body: some View {
        CustomStepper(value: $value, in: 1...10, onIncrement: onIncrement, onDecrement: onDecrement) {
            Text(String(value))
        }
        .onChange(of: value) {
            print("onChange value: \($0)")
        }
    }
    
    func onIncrement() {
        print("onIncrement")
    }

    func onDecrement() {
        print("onDecrement")
    }
}

一般来说,业务逻辑不应该出现在视图中,因为视图是不断创建和销毁的值。将其移动到ViewModel中。通过使用任何已发布属性的projectedValue获取发布者,可以查看该属性。例如:

import SwiftUI
import PlaygroundSupport
import Combine

final class ViewModel: ObservableObject {
  @Published var steps: Int = 0
  @Published var title: String = ""
  init() {
    $steps
      .handleEvents(receiveOutput: { value in
        // Perform your audio side effect for this value here
      })
      .map {"The current value is \($0)" }
      .assign(to: &$title)
  }
}

struct ContentView: View {
  @StateObject var viewModel = ViewModel()
  var body: some View {
    Stepper(viewModel.title, value: $viewModel.steps)
  }
}

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())

一般来说,业务逻辑不应该出现在视图中,因为视图是不断创建和销毁的值。将其移动到ViewModel中。通过使用任何已发布属性的projectedValue获取发布者,可以查看该属性。例如:

import SwiftUI
import PlaygroundSupport
import Combine

final class ViewModel: ObservableObject {
  @Published var steps: Int = 0
  @Published var title: String = ""
  init() {
    $steps
      .handleEvents(receiveOutput: { value in
        // Perform your audio side effect for this value here
      })
      .map {"The current value is \($0)" }
      .assign(to: &$title)
  }
}

struct ContentView: View {
  @StateObject var viewModel = ViewModel()
  var body: some View {
    Stepper(viewModel.title, value: $viewModel.steps)
  }
}

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())

感谢您的投入,游乐场非常酷,我完全同意业务逻辑不应该出现在视图中,我有一个视图模型,我编辑了我的问题,希望能更清楚。谢谢你的帮助,这对我来说意义重大,因为你的投入,这个游乐场非常酷,我完全同意业务逻辑不应该出现在视图中,我有一个视图模型,我编辑了我的问题,希望更清楚。谢谢你的帮助这对我很重要这对我很重要。我编辑了我的问题,以便更详细clear@MikeHaslam我想我现在明白问题所在了-请查看更新的答案。再次感谢您的帮助。当我感谢别人的帮助时,我保证会帮助别人。这对我来说意义重大。我编辑了我的问题,以便更详细clear@MikeHaslam我想我现在明白问题所在了-请查看更新的答案。再次感谢您的帮助。我答应尽可能帮助别人