71 lines
2.2 KiB
Swift
71 lines
2.2 KiB
Swift
//
|
|
// https://mczachurski.dev
|
|
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
|
// Licensed under the MIT License.
|
|
//
|
|
|
|
import CoreHaptics
|
|
|
|
public final class HapticService: ObservableObject {
|
|
public static let shared = HapticService()
|
|
|
|
private let hapticEngine: CHHapticEngine?
|
|
private var needsToRestart = false
|
|
|
|
/// Fires a transient haptic event with the given intensity and sharpness (0-1).
|
|
public func touch(intensity: Float = 0.75, sharpness: Float = 0.5) {
|
|
do {
|
|
let event = CHHapticEvent(
|
|
eventType: .hapticTransient,
|
|
parameters: [
|
|
CHHapticEventParameter(parameterID: .hapticIntensity, value: intensity),
|
|
CHHapticEventParameter(parameterID: .hapticSharpness, value: sharpness)
|
|
],
|
|
relativeTime: 0)
|
|
|
|
let pattern = try CHHapticPattern(events: [event], parameters: [])
|
|
let player = try hapticEngine?.makePlayer(with: pattern)
|
|
|
|
if needsToRestart {
|
|
try? start()
|
|
}
|
|
|
|
try player?.start(atTime: CHHapticTimeImmediate)
|
|
} catch {
|
|
print("Error \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
private init() {
|
|
hapticEngine = try? CHHapticEngine()
|
|
hapticEngine?.resetHandler = resetHandler
|
|
hapticEngine?.stoppedHandler = restartHandler
|
|
hapticEngine?.playsHapticsOnly = true
|
|
try? start()
|
|
}
|
|
|
|
/// Stops the internal CHHapticEngine. Should be called when your app enters the background.
|
|
public func stop(completionHandler: CHHapticEngine.CompletionHandler? = nil) {
|
|
hapticEngine?.stop(completionHandler: completionHandler)
|
|
}
|
|
|
|
/// Starts the internal CHHapticEngine. Should be called when your app enters the foreground.
|
|
public func start() throws {
|
|
try hapticEngine?.start()
|
|
needsToRestart = false
|
|
}
|
|
|
|
private func resetHandler() {
|
|
do {
|
|
try start()
|
|
} catch {
|
|
needsToRestart = true
|
|
}
|
|
}
|
|
|
|
private func restartHandler(_ reasonForStopping: CHHapticEngine.StoppedReason? = nil) {
|
|
resetHandler()
|
|
}
|
|
|
|
}
|