Skip to content

iOS 17 SwiftUI 中的 sensoryFeedback 视图修饰符

在 iOS 17 中,SwiftUI 引入了新的 sensoryFeedback 视图修饰符,用于为用户交互提供触觉反馈,提升用户体验。该修饰符提供多种预设反馈样式,并允许开发者灵活控制反馈的触发时机和类型。

基本使用

通过在视图上添加 .sensoryFeedback 修饰符即可实现触觉反馈。该修饰符接受两个参数:反馈样式和触发值。

swift
struct ContentView: View {
    @State var bool = false
    var body: some View {
        VStack {
            Button {
                print("点击了按钮")
                bool.toggle()
            } label: {
                Text("点我!")
            }
            // 当bool值变化时,触发成功样式的触觉反馈
            .sensoryFeedback(.success, trigger: bool)
        }
        .padding()
    }
}
struct ContentView: View {
    @State var bool = false
    var body: some View {
        VStack {
            Button {
                print("点击了按钮")
                bool.toggle()
            } label: {
                Text("点我!")
            }
            // 当bool值变化时,触发成功样式的触觉反馈
            .sensoryFeedback(.success, trigger: bool)
        }
        .padding()
    }
}

这段代码演示了如何使用 .sensoryFeedback(.success, trigger: bool) 在布尔值 bool 发生变化时触发“成功”样式的触觉反馈。

反馈样式

SwiftUI 提供了多种预定义的反馈样式,适用于不同的场景:

适用于 iOS 和 watchOS:

  • success:成功反馈,表示操作成功。
  • warning:警告反馈,提示用户需要注意的情况。
  • error:错误反馈,用于错误场景。
  • selection:选择反馈,UI 元素值更改时使用。
  • impact:冲击反馈,模拟物理冲击效果,可通过 weight(轻、中、重)、flexibility(刚性、柔软、实心)和 intensity(强度,默认为 1.0)自定义。

仅适用于 watchOS:

  • decrease:重要值减少到显著阈值以下时的反馈。
  • increase:重要值增加到显著阈值以上时的反馈。
  • start:表示活动的开始。
  • stop:表示活动的结束。

仅适用于 macOS:

  • alignment:拖动元素对齐时的震动反馈。
  • levelChange:按压力度相关场景的反馈,例如长按开启排序。

灵活控制反馈触发

使用条件闭包触发

可以使用条件闭包更灵活地控制反馈触发时机:

swift
.sensoryFeedback(.selection, trigger: store.selection) { oldValue, newValue in
    // 仅在选择更改为非空值时播放选择反馈
    return newValue != nil
}
.sensoryFeedback(.selection, trigger: store.selection) { oldValue, newValue in
    // 仅在选择更改为非空值时播放选择反馈
    return newValue != nil
}

闭包接收旧值和新值,返回布尔值指示是否播放反馈。

使用反馈闭包触发

使用反馈闭包可以控制播放的反馈类型:

swift
.sensoryFeedback(trigger: errorCode) { oldValue, newValue in
    if newValue == 0 {
        return SensoryFeedback.success
    } else {
        return SensoryFeedback.error
    }
}
.sensoryFeedback(trigger: errorCode) { oldValue, newValue in
    if newValue == 0 {
        return SensoryFeedback.success
    } else {
        return SensoryFeedback.error
    }
}

根据条件返回所需的反馈,或返回 nil 不播放任何反馈。