Реализация Core Haptics для iOS-приложения
Core Haptics появился в iOS 13 и работает на iPhone 8 и новее. В отличие от UIImpactFeedbackGenerator (заготовленные системные паттерны), Core Haptics позволяет создавать произвольные тактильные ощущения: форму нарастания, продолжительность, комбинацию вибрации и аудио-тона через один движок — CHHapticEngine.
Как устроен CHHapticEngine
Движок работает с событиями двух типов: CHHapticEvent.EventType.hapticTransient (короткий «клик», как нажатие кнопки) и CHHapticEvent.EventType.hapticContinuous (продолжительная вибрация). К каждому событию прикрепляются параметры: интенсивность (hapticIntensity), резкость (hapticSharpness).
import CoreHaptics
class HapticsManager {
private var engine: CHHapticEngine?
func prepareEngine() {
guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else { return }
do {
engine = try CHHapticEngine()
engine?.playsHapticsOnly = true
try engine?.start()
} catch {
print("CoreHaptics engine error: \(error)")
}
// Восстановление движка после прерывания (звонок, другое приложение)
engine?.resetHandler = { [weak self] in
try? self?.engine?.start()
}
engine?.stoppedHandler = { reason in
print("Haptic engine stopped: \(reason)")
}
}
}
playsHapticsOnly = true — если не нужен синхронизированный аудио-тон. Без этого флага CHHapticEngine также управляет аудио через CoreAudio, что требует настройки аудио-сессии.
Создание паттернов
Сложный паттерн — это массив CHHapticEvent с временными метками:
func playSuccessPattern() throws {
guard let engine = engine else { return }
let events: [CHHapticEvent] = [
// Быстрый клик
CHHapticEvent(
eventType: .hapticTransient,
parameters: [
CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.5),
CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.8)
],
relativeTime: 0
),
// Нарастающая вибрация
CHHapticEvent(
eventType: .hapticContinuous,
parameters: [
CHHapticEventParameter(parameterID: .hapticIntensity, value: 1.0),
CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.3)
],
relativeTime: 0.1,
duration: 0.4
),
// Финальный клик
CHHapticEvent(
eventType: .hapticTransient,
parameters: [
CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.8),
CHHapticEventParameter(parameterID: .hapticSharpness, value: 1.0)
],
relativeTime: 0.55
)
]
let pattern = try CHHapticPattern(events: events, parameters: [])
let player = try engine.makePlayer(with: pattern)
try player.start(atTime: CHHapticTimeImmediate)
}
hapticSharpness — субъективная «острота» вибрации: 1.0 это чёткий кликоподобный импульс, 0.0 — мягкое глубокое гудение. Комбинирование этих двух параметров во времени и даёт «характер» ощущения.
Динамическое изменение параметров
CHHapticDynamicParameter позволяет менять паттерн в реальном времени — например, усиливать вибрацию по мере нажатия на ползунок:
func updateIntensity(_ value: Float) {
let dynamicParam = CHHapticDynamicParameter(
parameterID: .hapticIntensityControl,
value: value,
relativeTime: 0
)
try? continuousPlayer?.sendParameters([dynamicParam], atTime: 0)
}
Это ключевая фича для игр и интерактивных интерфейсов: обратная связь изменяется в такт действию пользователя.
AHAP-файлы
Apple Haptic and Audio Pattern (.ahap) — JSON-формат для описания паттернов:
{
"Version": 1.0,
"Pattern": [
{
"Event": {
"Time": 0.0,
"Type": "HapticTransient",
"Parameters": [
{ "ParameterID": "HapticIntensity", "ParameterValue": 1.0 },
{ "ParameterID": "HapticSharpness", "ParameterValue": 0.5 }
]
}
}
]
}
Загрузка из файла: engine?.playPattern(from: url). Дизайнер может редактировать .ahap без изменения кода. Xcode имеет встроенный Core Haptics Composer для визуального создания паттернов.
Типичные проблемы
Движок останавливается при переходе приложения в background — CHHapticEngine.stoppedHandler вызывается с .applicationSuspended. При возврате в foreground нужно пересоздать или перезапустить движок. Обработчик resetHandler должен быть установлен до запуска.
Симулятор не поддерживает Core Haptics — тестировать только на реальном устройстве iPhone 8+. CHHapticEngine.capabilitiesForHardware().supportsHaptics вернёт false на симуляторе и iPad.
Задержка при первом запуске — инициализация CHHapticEngine занимает ~50–100 мс. Вызывайте prepareEngine() заранее, не в момент события.
Ориентиры по срокам
Базовые паттерны (2–3 типа) с правильной инициализацией движка и обработкой прерываний — 1 день. Динамические паттерны с реальтайм изменением параметров, AHAP-файлы, интеграция с игровыми событиями — 2–3 дня.







