7

I'm working with some UIGestures (in particular a force touch). I have all of that working, the additional UI updates/animations all working per the forced touch. However, I would like to add in the haptic touch feedback on the hard press. To my dismay, this snippet of code is not working. The function is called, interface updated, but no haptic feedback. Is there something I'm missing here? Permissions, capability, etc.?

@objc func forceTouchHandler(_ sender: ForceTouchGestureRecognizer) {
    print("force touch")
    UINotificationFeedbackGenerator().notificationOccurred(.success)
    self.updateInterface()
}

Thanks in advance for any feedback.

djneely
  • 1,074
  • 13
  • 25
  • What is `ForceTouchGestureRecognizer` and how does it work? – Yury Imashev Sep 21 '18 at 20:22
  • ForceTouchGestureRecognizer is a custom gesture recognizer to handle the forced touch gesture. That is all working and firing fine. I'm getting into this function handler and the self.updateInterface() method is called as well. Only thing not working here is the haptic response. – djneely Sep 22 '18 at 23:40
  • I'm sure it's working. But because you said that in other cases everything works fine, I suppose that some details of **how** does `ForceTouchGestureRecognizer` work exactly, possibly can explain why the system ignores your feedback notification. – Yury Imashev Sep 22 '18 at 23:45

5 Answers5

10

You don't need any permission to use feedback generator. It will not work when you're using a microphone. But in other cases everything should be fine. Try to call a prepare() method before notification.

let generator = UINotificationFeedbackGenerator()
generator.prepare()
generator.notificationOccurred(.success)
Yury Imashev
  • 2,068
  • 1
  • 18
  • 32
7

For me, the problem was haptics were disabled at a system level.

Settings -> Sounds & Haptics -> System Haptics

Ensure this is on.

Ric Santos
  • 15,419
  • 6
  • 50
  • 75
6

So, took a bit of digging but appears the issue was that I was testing on a iPhone 6 which does not support the UINotificationFeedbackGenerator. I figured since they provide the haptic touches on it, and no errors were being thrown all was right in the world.

So, here is what I wound up doing:

let modelName = UIDevice.modelName
if audioModels.contains(modelName) {
    AudioServicesPlaySystemSound(1519)
} else {
    UINotificationFeedbackGenerator().notificationOccurred(.success)
}

The UIDevice.modelName is just helper function I found on the internet (prob. Stack) that gets the device name. I then compare that name to a little array I setup - audioModels - of devices that need to have the audio played instead of using the NotificationFeedbackGenerator. Not sure if there is a better more intuitive way to check for the functionality per device (let me know if there is) but this is working for me.

Thanks again for looking into the issue.

Lookaji
  • 1,023
  • 10
  • 21
djneely
  • 1,074
  • 13
  • 25
  • For devices able to run iOS13+, import CoreHaptics. Then check this boolean: CHHapticEngine.capabilitiesForHardware().supportsHaptics – Marcy Nov 06 '21 at 01:40
2

Following this post for Haptic Engine to work we need this:

  1. The device needs to run iOS 10.0 or later.
  2. The device needs to be an iPhone 7 or later.
  3. The Haptic Engine needs to be turned on in device settings.

You are trying to do a touch feedback, so

UIImpactFeedbackGenerator().impactOccurred()

would be more appropriate.

For older devices you can use:

AudioServicesPlaySystemSound(1519)

To wrap-up, and with credit to Marcy, here is what works in iOS 13+:

import CoreHaptics
import AudioToolbox
    
func touchFeedback() {        
    if CHHapticEngine.capabilitiesForHardware().supportsHaptics {
        UIImpactFeedbackGenerator().impactOccurred()
    } else {
        AudioServicesPlaySystemSound(1519) // 1520 and 1521 are gradually stronger
    }
 }

For additional control, UIImpactFeedbackGenerator has 5 styles, default is .light, but there's also .soft, .medium, .heavy, .rigid. You get them in the initializer, e.g.:

UIImpactFeedbackGenerator(style: .rigid).impactOccurred()
soundflix
  • 928
  • 9
  • 22
0

If haptic feedback not enabled in iphone settings you can use AudioServicesPlaySystemSound or AudioServicesPlayAlertSound in order to get vibration anyway.

I've made an investigation and find only these types of sound that makes a vibration:

1519, 1520, 1521, kSystemSoundID_Vibrate

Example: AudioServicesPlaySystemSound(1521), AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)

Note: 1352 is same as kSystemSoundID_Vibrate

Nike Kov
  • 12,630
  • 8
  • 75
  • 122