我Core Haptics
在我的应用程序中使用来实现使用简单无法完成的自定义振动UIImpactFeedbackGenerator
然后我执行以下操作 -
- 实例化引擎
- 启动发动机
- 实例化 CHHapticPatternPlayer
- 启动播放器
播放振动的功能 -
func playContinuousVibration() {
do {
let pattern = try continuousVibration()
try hapticEngine.start()
let player = try hapticEngine.makePlayer(with: pattern)
try player.start(atTime: CHHapticTimeImmediate)
hapticEngine.notifyWhenPlayersFinished { _ in
return .stopEngine
}
} catch {}
}
Firebase 崩溃堆栈跟踪
崩溃:com.apple.root.default-qos EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000010
CoreHaptics __31-[CHHapticEngine handleFinish:]_block_invoke.306 + 276
libdispatch.dylib _dispatch_call_block_and_release + 32
libsystem_pthread.dylib start_wqthread + 8
编辑 1 - 在此处发布整个课程代码,为读者提供更多上下文
final class CustomHapticFeedback {
private let duration: Int
private let amplitude: SwFeedbackImpactType?
private var coreHapticsManager: Any? //Purposely made as Any to avoid using #available keyword everywhere
init(duration: Int, amplitude: String) {
self.duration = duration
self.amplitude = SwFeedbackImpactType(rawValue: amplitude)
}
//This function will perform either UIKit haptic feedback or Core Haptics feedback depending on device and OS compatibility
func performVibrateAction() {
if #available(iOS 13.0, *) {
guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else {
performUIKitHapticFeedback()
return
}
performCoreHapticFeedback()
} else {
performUIKitHapticFeedback()
}
}
private func performUIKitHapticFeedback() {
if let amplitude = amplitude {
SwHaptic.impact(amplitude.value).generate()
}
}
private func performCoreHapticFeedback() {
if #available(iOS 13.0, *) {
/*
Currently Core Haptics is not being used anywhere else apart from Gamification flow hence creating a new instance of
CoreHapticsManager everytime. Once this is being used in multiple places we can think of persisting it
*/
coreHapticsManager = CoreHapticsManager(duration: duration, amplitude: amplitude ?? .light)
if let manager = coreHapticsManager as? CoreHapticsManager {
manager.playContinuousVibration()
}
}
}
}
@available(iOS 13.0, *)
final class CoreHapticsManager {
private let hapticEngine: CHHapticEngine
private let duration: Int
private let amplitude: SwFeedbackImpactType
init?(duration: Int, amplitude: SwFeedbackImpactType) {
self.duration = duration
self.amplitude = amplitude
let hapticCapability = CHHapticEngine.capabilitiesForHardware()
guard hapticCapability.supportsHaptics else {
return nil
}
do {
hapticEngine = try CHHapticEngine()
} catch _ {
return nil
}
}
func playContinuousVibration() {
do {
let pattern = try continuousVibration()
try hapticEngine.start()
let player = try hapticEngine.makePlayer(with: pattern)
try player.start(atTime: CHHapticTimeImmediate)
hapticEngine.notifyWhenPlayersFinished { _ in
return .stopEngine
}
} catch {}
}
}
@available(iOS 13.0, *)
extension CoreHapticsManager {
//Below function will play a continuous vibration for a constant period of time
private func continuousVibration() throws -> CHHapticPattern {
let hapticIntensity: Float
switch amplitude {
case .light:
hapticIntensity = 0.7
case .medium:
hapticIntensity = 0.85
case .heavy:
hapticIntensity = 1.0
}
let continuousVibrationEvent = CHHapticEvent(
eventType: .hapticContinuous,
parameters: [
CHHapticEventParameter(parameterID: .hapticIntensity, value: hapticIntensity)
],
relativeTime: 0,
duration: (Double(duration)/1000))
return try CHHapticPattern(events: [continuousVibrationEvent], parameters: [])
}
}
编辑2:
enum SwFeedbackImpactType: String {
case light, medium, heavy
var value: UIImpactFeedbackGenerator.FeedbackStyle {
switch self {
case .light:
return .light
case .medium:
return .medium
case .heavy:
return .heavy
}
}
}
编辑 3:使 Haptic Player 成为类的成员,而不是在函数内部实例化
@available(iOS 13.0, *)
final class CoreHapticsManager {
private let hapticEngine: CHHapticEngine
private let duration: Int
private let amplitude: SwFeedbackImpactType
private var player: CHHapticPatternPlayer?
init?(duration: Int, amplitude: SwFeedbackImpactType) {
self.duration = duration
self.amplitude = amplitude
let hapticCapability = CHHapticEngine.capabilitiesForHardware()
guard hapticCapability.supportsHaptics else {
return nil
}
do {
hapticEngine = try CHHapticEngine()
} catch _ {
return nil
}
}
func playContinuousVibration() {
do {
let pattern = try continuousVibration()
try hapticEngine.start()
player = try hapticEngine.makePlayer(with: pattern)
try player?.start(atTime: CHHapticTimeImmediate)
hapticEngine.notifyWhenPlayersFinished { _ in
return .stopEngine
}
} catch {}
}
}