@@ -359,6 +359,15 @@ - (instancetype)initWithController:(GCController*)controller MFI_RUMBLE_AVAIL
359359 [self .engines addObject: engine];
360360
361361 __weak MFIRumbleController *weakSelf = self;
362+ engine.stoppedHandler = ^(CHHapticEngineStoppedReason reason) {
363+ MFIRumbleController *strongSelf = weakSelf;
364+ if (!strongSelf)
365+ return ;
366+
367+ /* Engine stopped (backgrounding/interruption) - clear players but keep engine in set */
368+ strongSelf->_strongPlayer = nil ;
369+ strongSelf->_weakPlayer = nil ;
370+ };
362371 engine.resetHandler = ^{
363372 MFIRumbleController *strongSelf = weakSelf;
364373 if (!strongSelf)
@@ -416,12 +425,18 @@ - (void)shutdown
416425{
417426 if (@available (iOS 14 , tvOS 14 , macOS 11 , *))
418427 {
428+ if (_weakPlayer) [_weakPlayer cancelAndReturnError: nil ];
429+ if (_strongPlayer) [_strongPlayer cancelAndReturnError: nil ];
430+
419431 for (CHHapticEngine *eng in self.engines )
432+ {
433+ eng.stoppedHandler = ^(CHHapticEngineStoppedReason reason) {};
420434 eng.resetHandler = ^{};
435+ [eng stopWithCompletionHandler: nil ];
436+ }
421437 [self .engines removeAllObjects ];
422- if (_weakPlayer) [_weakPlayer cancelAndReturnError: nil ];
423- _weakPlayer = nil ;
424- if (_strongPlayer) [_strongPlayer cancelAndReturnError: nil ];
438+
439+ _weakPlayer = nil ;
425440 _strongPlayer = nil ;
426441 }
427442}
@@ -553,9 +568,9 @@ static void apple_gamecontroller_device_haptics_setup(void) IPHONE_RUMBLE_AVAIL
553568
554569 deviceHapticEngine.stoppedHandler = ^(CHHapticEngineStoppedReason reason)
555570 {
571+ /* Engine stopped (backgrounding/interruption) - clear players but keep engine */
556572 deviceWeakPlayer = nil ;
557573 deviceStrongPlayer = nil ;
558- deviceHapticEngine = nil ;
559574 };
560575 deviceHapticEngine.resetHandler = ^{
561576 if (!deviceHapticEngine)
@@ -573,10 +588,23 @@ static void apple_gamecontroller_device_haptics_setup(void) IPHONE_RUMBLE_AVAIL
573588 if (!deviceHapticEngine)
574589 return nil ;
575590
591+ /* Ensure engine is started (may have been stopped by backgrounding) */
592+ NSError *error;
593+ [deviceHapticEngine startAndReturnError: &error];
594+ if (error)
595+ {
596+ /* Engine couldn't start - recreate it */
597+ deviceHapticEngine = nil ;
598+ deviceWeakPlayer = nil ;
599+ deviceStrongPlayer = nil ;
600+ apple_gamecontroller_device_haptics_setup ();
601+ if (!deviceHapticEngine)
602+ return nil ;
603+ }
604+
576605 CHHapticEventParameter *intense;
577606 CHHapticEvent *event;
578607 CHHapticPattern *pattern;
579- NSError *error;
580608
581609 CHHapticEventParameter *sharp;
582610
@@ -654,7 +682,24 @@ static void apple_gamecontroller_device_haptics_setup(void) IPHONE_RUMBLE_AVAIL
654682 return (void *)-1 ;
655683}
656684
657- static void apple_gamecontroller_joypad_destroy (void ) { }
685+ static void apple_gamecontroller_joypad_destroy (void )
686+ {
687+ #if TARGET_OS_IOS
688+ if (@available (iOS 14 , *))
689+ {
690+ if (deviceHapticEngine)
691+ {
692+ deviceHapticEngine.stoppedHandler = ^(CHHapticEngineStoppedReason reason) {};
693+ deviceHapticEngine.resetHandler = ^{};
694+ [deviceHapticEngine stopWithCompletionHandler: ^(NSError *error) {
695+ deviceWeakPlayer = nil ;
696+ deviceStrongPlayer = nil ;
697+ deviceHapticEngine = nil ;
698+ }];
699+ }
700+ }
701+ #endif
702+ }
658703
659704static int32_t apple_gamecontroller_joypad_button (
660705 unsigned port, uint16_t joykey)
0 commit comments