mkuczera / react-native-haptic-feedback

React-Native Haptic Feedback for iOS with Android similar behaviour.
MIT License
855 stars 103 forks source link

What is the maximum duration time of vibration in ios #98

Open davidg327 opened 1 year ago

davidg327 commented 1 year ago

Description

I am making an exercise app, and I have the haptic activated when the round starts, the problem is that a round lasts 50 seconds, if it passes 25 seconds it stops vibrating, this only happens on iOS, I would like to know if there is a restriction in the library about the maximum haptic time, this problem in android does not happen.

My example code

const options = { enableVibrateFallback: false, ignoreAndroidSystemSettings: true };

const interval = useRef(null);

const hapticLight = () => { trigger("impactLight", options) }

useEffect(() => { interval.current = setInterval(() => { hapticLight() }, 100); return () => clearInterval(interval.current); }, []);

Package version "react": "17.0.2", "react-native": "0.66.5", "react-native-haptic-feedback": "^2.0.0",

Example visual

Captura de pantalla 2023-05-25 a la(s) 7 19 09 p m
vanko0309 commented 1 year ago

I have the same issue, is there any limitation, or property that needs to be set?

siliconivan commented 3 months ago

A bit of a hack, but I had a similar issue and switched the trigger method to notificationSuccess and no longer had the issue. It felt similar enough for our use case.

jpitkanen17 commented 3 weeks ago

I resolved this with the following patch, hope it's of any use.

react-native-haptic-feedback+2.2.0.patch

diff --git a/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedback.mm b/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedback.mm
index cf75baf..1ca2da3 100644
--- a/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedback.mm
+++ b/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedback.mm
@@ -100,11 +100,10 @@ RCT_EXPORT_METHOD(trigger:(NSString *)type options:(NSDictionary *)options)
         impactGeneratorMap = [[NSMutableDictionary alloc] init];
     if ([impactGeneratorMap objectForKey:key] == nil){
         [impactGeneratorMap setValue:[[UIImpactFeedbackGenerator alloc] initWithStyle:style] forKey:key];
-        [[impactGeneratorMap objectForKey:key] prepare];
     }
-    UIImpactFeedbackGenerator *generator = [impactGeneratorMap objectForKey:key];
-    [generator impactOccurred];
-    [generator prepare];
+    [[impactGeneratorMap objectForKey:key] prepare];
+    [[impactGeneratorMap objectForKey:key] performSelector:@selector(impactOccurred) withObject: nil afterDelay:0.0f];
+    [[impactGeneratorMap objectForKey:key] prepare];
 }

 -(void)generateNotificationFeedback:(UINotificationFeedbackType)notificationType{
mkuczera commented 2 weeks ago

Is this related to a limitation of iOS regarding the haptics? Would be glad to have a reference, but couldn´t find anything. The diff is only triggering the prepare again, or am i missing something @jpitkanen17

jpitkanen17 commented 2 weeks ago

Is this related to a limitation of iOS regarding the haptics? Would be glad to have a reference, but couldn´t find anything. The diff is only triggering the prepare again, or am i missing something @jpitkanen17

@mkuczera The extra prepare call might be redundant and something I tried before figuring the real solution out.

The actual solution is this call [[impactGeneratorMap objectForKey:key] performSelector:@selector(impactOccurred) withObject: nil afterDelay:0.0f];

The key difference is the delay 0.0f which overrides the previous haptics call. I tested this with a slider that would stop vibrating on every click after a while and this fixed it. The only "bug" is that sometimes the you can feel the vibration being cancelled.