Реалізація 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 дні.







