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
套件来存储与音频相关的设置。
@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 秒,则不会播放。
要添加自定义音频反馈类型
CustomSoundRepresentable
的枚举enum MyCustomSound: CustomSoundRepresentable {
case tupperwareFallingOutOfCrampedCupboard
var soundFile: SoundFile {
switch self {
case .tupperwareFallingOutOfCrampedCupboard:
Soundfile(name: "tupperwareFallingOutOfCrampedCupboard", extension: .aif)
}
}
}
确保文件名和扩展名正确,并已加载到您的应用程序主包中。
在您的应用程序中使用自定义反馈
@State private var isError: Bool = false
Button("Show error") {
isError.toggle()
}
.audioFeedback(.custom(MyCustomSound.tupperwareFallingOutOfCrampedCupboard), trigger: isError)
欢迎随时贡献!欢迎随时提交 pull request 或打开 issue,提出您的建议或改进。
AudioManager
在 MIT 许可证下获得许可。 有关更多详细信息,请参见 LICENCE 文件。