AudioManager

Swift Versions

Platforms

Licence

AudioManager 是一个 Swift 软件包,提供了一个模块化且易于使用的接口,用于在您的应用程序中实现音频反馈。它可以与 SwiftUI 无缝集成,使您可以通过可自定义的听觉反馈来增强用户体验。

特性

安装

使用 Swift Package Manager 将 AudioManager 添加到您的 Swift 项目。

dependencies: [
  .package(url: "https://github.com/markbattistella/AudioManager", from: "1.0.0")
]

使用方法

有三种使用 AudioManager 的方式:

注意

虽然有 .system() Playback 调用,但它仅在 iOS 上可用,因为这些内置声音位于 iOS 上。 所有其他用途都可以使用 .custom() 选项。

静态操作

静态操作格式允许您一致且简单地触发音频反馈。在下面的示例中,每当 isSuccess 状态更改时,就会触发音频反馈。

@State private var isSuccess: Bool = false

Button("isSuccess: \(isSuccess)") {
  isSuccess.toggle()
}
.audioFeedback(.system(.ui(.tock)), trigger: isSuccess)

带条件的静态操作

您还可以使用条件来控制何时应触发音频反馈,从而可以更专注于控制反馈何时发生。

旧值和新值

enum Phase { case inactive, active, completed }

@State private var phase: Phase = .inactive

Button("Update phase") {
  switch phase {
    case .inactive: phase = .active
    case .active: phase = .completed
    case .completed: phase = .inactive
  }
}
.audioFeedback(.system(.ui(.tink)), trigger: phase) { oldValue, newValue in
  oldValue != .completed && newValue == .completed
}

仅新值

enum Phase { case inactive, active, completed }

@State private var phase: Phase = .inactive

Button("Update phase") {
  switch phase {
    case .inactive: phase = .active
    case .active: phase = .completed
    case .completed: phase = .inactive
  }
}
.audioFeedback(.system(.ui(.tink)), trigger: phase) { newValue in
  newValue == .completed
}

无参数

@State private var phase: Bool = false

Button("Toggle Phase") {
  phase.toggle()
}
.audioFeedback(.system(.ui(.tink)), trigger: phase) {
  // Audio feedback triggered
}

动态操作

动态操作方法使您可以完全控制反馈的类型以及触发反馈的条件。

旧值和新值

enum LoadingState { case ready, success, failure }

@State private var loadingState: LoadingState = .ready

Button("Update loading state") {
  switch loadingState {
    case .ready: loadingState = .success
    case .success: loadingState = .failure
    case .failure: loadingState = .ready
  }
}
.audioFeedback(trigger: loadingState) { oldValue, newValue in
  switch (oldValue, newValue) {
    case (.failure, .ready):
      return .system(.modern(.cameraShutterBurstBegin))
    case (.ready, .success):
      return .system(.nano(.screenCapture))
    case (.success, .failure):
      return .system(.new(.update))
    default:
      return nil
  }
}

仅新值

enum LoadingState { case ready, success, failure }

@State private var loadingState: LoadingState = .ready

Button("Update loading state") {
  switch loadingState {
    case .ready: loadingState = .success
    case .success: loadingState = .failure
    case .failure: loadingState = .ready
  }
}
.audioFeedback(trigger: loadingState) { newValue in
  switch newValue {
    case .success: return .system(.modern(.cameraShutterBurstBegin))
    case .failure: return .system(.nano(.screenCapture))
    default: return nil
  }
}

无参数

enum LoadingState { case ready, success, failure }

@State private var loadingState: LoadingState = .ready

Button("Update loading state") {
  switch loadingState {
    case .ready: loadingState = .success
    case .success: loadingState = .failure
    case .failure: loadingState = .ready
  }
}
.audioFeedback(trigger: loadingState) {
  // Audio feedback triggered
}

配置音频设置

AudioManager 包含一个 .audioEffectsEnabled UserDefaults 键,允许您根据用户设置动态启用或禁用音频。

如果您想添加一个设置屏幕来切换音频音效,或者您需要一个整体逻辑来控制音频(例如,将其作为一项高级功能),这将非常有用。

内置 UserDefaults 套件

该软件包使用内部公开的 UserDefaults 套件来存储与音频相关的设置。

@main
struct MyAwesomeApp: App {

  init() {
    UserDefaults.audio.register([
      AudioUserDefaultsKey.audioEffectsEnabled : true
    ])
  }

  var body: some Scene {
    WindowGroup { ... }
  }
}

或者手动更新它

Button("Turn audio off") {
  UserDefaults.audio.set(false, for: AudioUserDefaultKeys.isAudioEnabled)
}

Button("Turn audio on") {
  UserDefaults.audio.set(true, for: AudioUserDefaultKeys.isAudioEnabled)
}

重要说明

虽然您可以将 UserDefaults 注册到任何套件(.standard 或自定义),但该软件包只会响应内部 .audio 套件,以防止应用程序的不同部分之间发生意外冲突。

扩展音频反馈类型

如果内置的反馈类型不足,您可以使用自己的自定义音频文件,方法是使用 .custom(CustomSoundRepresentable) Playback case。

自定义文件限制

允许的音频文件扩展名有限:.aif.aiff.caf.mp3.wav

而且您的音频文件限制为 30 秒。如果超过 30 秒,则不会播放。

创建自定义反馈

要添加自定义音频反馈类型

  1. 定义一个符合 CustomSoundRepresentable 的枚举
enum MyCustomSound: CustomSoundRepresentable {
    case tupperwareFallingOutOfCrampedCupboard

    var soundFile: SoundFile {
        switch self {
            case .tupperwareFallingOutOfCrampedCupboard:
              Soundfile(name: "tupperwareFallingOutOfCrampedCupboard", extension: .aif)
        }
    }
}
  1. 确保文件名和扩展名正确,并已加载到您的应用程序主包中。

  2. 在您的应用程序中使用自定义反馈

@State private var isError: Bool = false

Button("Show error") {
  isError.toggle()
}
.audioFeedback(.custom(MyCustomSound.tupperwareFallingOutOfCrampedCupboard), trigger: isError)

贡献

欢迎随时贡献!欢迎随时提交 pull request 或打开 issue,提出您的建议或改进。

许可证

AudioManager 在 MIT 许可证下获得许可。 有关更多详细信息,请参见 LICENCE 文件。