4

前言

SwiftUI 引入了新的 sensoryFeedback 视图修饰符,使我们能够在所有 Apple 平台上播放触觉反馈。下面我们将学习如何使用 sensoryFeedback 修饰符在应用程序中的不同操作中提供触觉反馈。

背景介绍

在 iOS 17 之前,如果你想要从 SwiftUI 视图中向用户提供触觉反馈,你会使用其中一个 UIKit(或 AppKit)的反馈生成器。例如,使用选择反馈生成器:

struct ListView: View {
  @Binding var store: Store
  let generator = UISelectionFeedbackGenerator()
  
  var body: some View {
    List(store.items, selection: $store.selection) { ... }
    .onChange(of: store.selection) { oldValue, newValue in
      if newValue != nil {
        generator.selectionChanged()
      }
    }
  }
}

在 iOS 17 中,Apple 直接向 SwiftUI 中添加了一系列感觉反馈的视图修饰符,以播放触觉和/或音频反馈。

平台支持

并非所有平台都支持所有反馈选项。以下是我所知道的每个平台上可用的内容列表。请注意,iPad不支持触觉反馈。

仅支持watchOS

  • start:活动开始
  • stop:活动停止

支持watchOS和iOS

  • decrease:重要值减少到显着阈值以下
  • increase:重要值增加到显着阈值以上
  • selection:UI元素的值正在更改
  • success:任务成功完成
  • warning:任务产生警告
  • error:任务产生错误
  • impact:UI元素碰撞时的物理冲击

请注意,impact反馈有两个变体,让您指定元素碰撞的重量(轻,中,重)或灵活性(刚性,柔软,实心)。在这两种情况下,您还可以更改强度(默认为1.0):

// 默认impact反馈
.impact()

// 具有柔韧性并增加强度的impact
.impact(flexibility: .rigid, intensity: 2.0)

// 具有重量并增加强度的impact
.impact(weight: .heavy, intensity: 2.0)

基本用法

要在 SwiftUI 视图中播放触觉反馈,我们只需要使用 sensoryFeedback 视图修饰符,带有两个参数。第一个定义了反馈样式,第二个是触发器值。

struct ContentView: View {
    @State private var store = Store()
    
    var body: some View {
        NavigationStack {
            List(store.results, id: \.self) { result in
                Text(result)
            }
            .searchable(text: $store.query)
            .sensoryFeedback(.success, trigger: store.results)
        }
    }
}

在上面的示例中,我们使用 sensoryFeedback 视图修饰符,带有成功样式。我们还将存储的 results 属性定义为触发器。这意味着 SwiftUI 将在存储的结果更改时播放成功样式的触觉反馈。

预定义样式

SwiftUI 提供了许多预定义的反馈样式,如 successwarningerrorselectionincreasedecreasestartstopalignmentlevelChangeimpact 等。

struct ContentView: View {
    @State private var trigger = false
    
    var body: some View {
        NavigationStack {
            Button("Action") {
                // 进行某些操作
                trigger.toggle()
            }
            .sensoryFeedback(
                .impact(weight: .heavy, intensity: 0.9),
                trigger: trigger
            )
        }
    }
}

如上所示,impact 样式允许我们调整反馈的权重和强度。请记住,最好使用预定义的样式,并在超级自定义的情况下自定义触觉反馈。

根据触发器值选择样式

sensoryFeedback 视图修饰符的另一种变体允许我们根据触发器值选择特定的反馈样式。在这里,我们在存储包含结果时播放成功反馈,并在结果为空时播放错误反馈。

struct ContentView: View {
    @State private var store = Store()
    
    var body: some View {
        NavigationStack {
            List(store.results, id: \.self) { result in
                Text(result)
            }
            .searchable(text: $store.query)
            .sensoryFeedback(trigger: store.results) { oldValue, newValue in
                return newValue.isEmpty ? .error : .success
            }
        }
    }
}

SwiftUI 还提供了在触发器值上定义条件的选项,决定是否播放预定义的反馈样式。

使用场景

这些感觉反馈修饰符都是基于触发器的。触发器需要是可等同的类型。有三种感觉反馈视图修饰符的变体:

当值更改时触发

struct ListView: View {
  @Binding var store: Store
    
  var body: some View {
    List(store.items, selection: $store.selection) { ... }
    .sensoryFeedback(.selection, trigger: store.selection)
  }
}

视图修饰符的第一个参数是 SensoryFeedback 类型。并非所有反馈类型都适用于所有平台。当触发器值更改时,反馈会播放。

使用条件闭包触发

如果要更灵活地控制何时触发反馈,请使用带有条件闭包版本的视图修饰符。例如,仅在选择更改为非空值时播放选择反馈:

.sensoryFeedback(.selection, trigger: store.selection) {
  oldValue, newValue in
    newValue != nil
}

条件闭包接收监视的触发器值的旧值和新值。在闭包中,返回一个布尔值,指示是否应播放反馈。

使用反馈闭包触发

要控制播放何种反馈,请使用视图修饰符的反馈闭包版本。例如,基于错误代码提供警告或错误反馈:

// @State private var errorCode: Int = 0

.sensoryFeedback(trigger: errorCode) { oldValue, newValue in
    switch newValue {
    case 1: .warning
    case 2: .error
    default: nil
    }
}

在这种情况下,在闭包中返回所需的反馈,如果不想要任何反馈,则返回nil。

可以运行 Demo

提供一个可以运行的 Demo,完整代码如下:

import SwiftUI

struct ContentView: View {
    @State private var store = Store()
    
    var body: some View {
        NavigationView {
            List(store.results, id: \.self) { result in
                Text(result)
            }
            .searchable(text: $store.query)
            .sensoryFeedback(.success, trigger: store.results)
            .navigationTitle("Sensory Feedback Demo")
        }
    }
}

struct Store {
    @State var query: String = ""
    @State var results: [String] = ["Result 1", "Result 2", "Result 3"]
}

Demo 包括一个带有触觉反馈的 SwiftUI 列表。你可以根据需要进行进一步的调整和扩展。

总结

SwiftUI引入了新的sensoryFeedback视图修饰符,为所有Apple平台提供触觉反馈。通过简单的附加,我们可以定义反馈样式和触发器值,实现了在应用程序中不同操作产生的触觉效果。支持多种预定义样式,如success、warning、error,以及个性化的impact样式。对于触发器值的处理也非常灵活,可以根据其条件选择不同的反馈样式。

总体而言,这个新的视图修饰符为提高应用的可访问性和用户体验提供了简便的方式。在使用时需谨慎,避免过多干扰用户。希望通过学习这个新特性,开发者能更好地运用触觉反馈功能,提升应用的交互性。


Swift社区
11.9k 声望3.8k 粉丝

我们希望做一个最专业最权威的 Swift 中文社区,我们希望更多的人学习和使用Swift。我们会分享以 Swift 实战、SwiftUI、Swift 基础为核心的技术干货,欢迎您的关注与支持。