Hello,
We are trying to do some advanced stuff with CoreHaptics where we need to navigate in the haptic pattern (start, pause, resume, rewind or fast forward). But it seems like the seek(toOffset:) method of CHHapticAdvancedPatternPlayer doesn't work on iOS 14 and iOS 15.
Here's a sample code :
import CoreHaptics
import Foundation
import SwiftUI
let events = [
CHHapticEvent(
eventType: .hapticContinuous,
parameters: [
CHHapticEventParameter(parameterID: .hapticSharpness, value: 1),
CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.8)
],
relativeTime: 0,
duration: 3
)
]
let parameters = [
CHHapticDynamicParameter(parameterID: .hapticIntensityControl, value: 1, relativeTime: 0),
CHHapticDynamicParameter(parameterID: .hapticIntensityControl, value: 0.5, relativeTime: 0.5),
CHHapticDynamicParameter(parameterID: .hapticIntensityControl, value: 1, relativeTime: 1),
CHHapticDynamicParameter(parameterID: .hapticIntensityControl, value: 0.5, relativeTime: 1.5),
CHHapticDynamicParameter(parameterID: .hapticIntensityControl, value: 1, relativeTime: 2),
CHHapticDynamicParameter(parameterID: .hapticIntensityControl, value: 0.5, relativeTime: 2.5)
]
let pattern = try! CHHapticPattern(events: events, parameters: parameters)
struct ContentView: View {
private var player: CHHapticAdvancedPatternPlayer?
var body: some View {
VStack(spacing: 20) {
Button("Start") {
try? player?.start(atTime: CHHapticTimeImmediate)
}
Button("Pause") {
try? player?.pause(atTime: CHHapticTimeImmediate)
}
Button("Resume") {
try? player?.resume(atTime: CHHapticTimeImmediate)
}
Button("Stop") {
try? player?.stop(atTime: CHHapticTimeImmediate)
}
Button("Seek to offset 1 sec") {
do {
try player?.seek(toOffset: 1)
print("No error")
} catch {
print(error)
}
}
}
}
init() {
guard CHHapticEngine.capabilitiesForHardware().supportsHaptics,
let engine = try? CHHapticEngine()
else { return }
engine.resetHandler = { try? engine.start() }
try? engine.start()
self.player = try? engine.makeAdvancedPlayer(with: pattern)
print(pattern.duration)
}
}
Is there anything wrong with the code ? Can someone provide a working example ?
Thanks !
I had not noticed at first that you are playing a single long continuous event, and then attempting to seek on it. This is a known issue described here in the Core Haptics Release Notes:
Events — such as audioContinuous, hapticContinuous, and audioCustom — can’t be resumed during the event; no output occurs for that event, only for subsequent events. This applies to playback at a specific time offset, seeking, and resuming.(29274583)
The best workaround is to convert your pattern into a series of three shorter continuous events - or even into smaller events if possible. That way the pattern will continue to play at the next event it hits, regardless of where you are in the timeline.
Hope this helps you get this working.
-DS