[SwiftUI] 전역적인 햅틱 관리 HapticsManager 2.2.0
https://github.com/markbattistella/HapticsManager
GitHub - markbattistella/HapticsManager: HapticsManager is a Swift package that provides a modular and easy-to-use interface for
HapticsManager is a Swift package that provides a modular and easy-to-use interface for implementing haptic feedback in your applications. It integrates seamlessly with SwiftUI, enabling you to enh...
github.com
앱을 만들면서 전역적으로 햅틱(진동) 사용을 온/오프할 수 있는 기능이 필요했다.
SwiftUI 5(iOS 17)부터는 .sensoryFeedback 같은 내장 API도 있지만,
이 방식은 앱을 껐다 켜면 설정이 유지되지 않고, 전역 상태 관리도 불편하다.
그래서 HapticsManager 라이브러리를 도입했다.
1. 앱 시작 시 전역 설정값 등록
공식 문서에는 아래처럼 등록하라고 안내되어 있다.
@main
struct MyAwesomeApp: App {
init() {
UserDefaults.haptic.register([
HapticUserDefaultsKey.hapticEffectsEnabled : true
])
}
var body: some Scene {
WindowGroup { ... }
}
}
하지만 실제로는 위 코드가 동작하지 않는다.
UserDefaults 내부 네이밍과 선언 방법이 바뀌어서 아래처럼 써야 정상적으로 동작한다.
UserDefaults.haptics.register(defaults: [
HapticUserDefaultsKey.hapticEffectsEnabled.rawValue: true
])
라이브러리 업뎃이 멈췃는지 이렇게 해줘야한다.
전역적인 진동 설정 값 관리
@AppStorage(HapticUserDefaultsKey.hapticEffectsEnabled.rawValue, store: .haptics)
var isHapticsEnabled: Bool = true
Button("Turn haptics off") {
UserDefaults.haptics.set(false, for: HapticUserDefaultsKey.hapticEffectsEnabled.rawValue)
}
Button("Turn haptics on") {
UserDefaults.haptics.set(true, for: HapticUserDefaultsKey.hapticEffectsEnabled.rawValue)
}
버튼에서 햅틱 사용
HapticsManager는 SwiftUI의 View Modifier 방식으로 햅틱을 적용한다.
import HapticsManager
@State private var isSuccess: Bool = false
Button(action: { isSuccess.toggle() }) {
Text("구르기")
}
.hapticFeedback(.impact(.medium), trigger: isSuccess)
트리거 방식의 아쉬움
햅틱 설정은 전역적으로 관리하면서, 실제 실행은 지역 변수 트리거를 통해 이루어지는 구조가 비효율적으로 느껴진다.
버튼을 누르는 행위 자체가 트리거가 될 수 있을 텐데, 굳이 별도의 상태 변수를 만들어서 토글해야 한다는 점이 아쉽다.
SwiftUI의 Modifier 시스템이 "값의 변화"에 반응하는 구조라 어쩔 수 없는 부분이지만,
페이지가 많아질수록 이 패턴을 반복하는 게 번거롭게 느껴진다.
개선 방향
현 시점에서는 HapticsManager의 전역 설정값을 활용해 앱 전체 진동 온/오프를 안전하게 관리할 수 있다.
하지만, 버튼마다 별도의 트리거 변수를 만들어야 하는 구조는 대규모 프로젝트에서 불편할 수 있다.
임시로 이 구조를 사용하되, 추후에는 전역적으로 사용할 수 있는 햅틱 래퍼 함수나 커스텀 버튼 컴포넌트로 개선하는 방안을 적용해야겠다.
(그치만 버튼마다 디자인이 달라서...)