Skip to content

[iOS] Crash on VoipPushNotification.registerVoipToken() when running on Expo Dev Client (Windows) #119

@siblonet

Description

@siblonet

🧠 Summary

When running a React Native + Expo app using react-native-voip-push-notification,
the app crashes instantly on iOS when calling:

VoipPushNotification.registerVoipToken();

This happens on both:

  • Expo Dev Client (built via expo run:ios / eas build --profile development)

  • TestFlight release build

I submitted to the App Store only to get a readable crash report because I’m developing on Windows + VSCode, with no access to Xcode logs.

💥 Crash Reason

From Apple crash logs:

Exception Type: EXC_CRASH (SIGABRT) Exception Reason: -[(dynamic class) pushRegistry:didUpdatePushCredentials:forType:]: unrecognized selector sent to instance

⚙️ Environment

Key | Version / Platform -- | -- Expo SDK | 53.0.9 React Native | 0.79.2 react-native-voip-push-notification | 3.3.3 react-native-callkeep | (4.3.16) Platform | iOS only Build type | Expo EAS (managed workflow + dev-client) Computer | Windows 10 (no Xcode access) Device | Real iPhone (via TestFlight + Dev Client)

🧩 Steps to Reproduce

  1. Create Expo project with:

    npx create-expo-app myapp
  2. Install:

    npm install react-native-voip-push-notification react-native-callkeep
  3. Add to JS code:

    import VoipPushNotification from 'react-native-voip-push-notification'; VoipPushNotification.registerVoipToken();
  4. Build iOS dev client:

    eas build --platform ios --profile development
  5. Run the app on device → instant crash.


🧠 Analysis

  • The crash happens because PushKit is trying to call:

    pushRegistry:didUpdatePushCredentials:forType:

    on AppDelegate.

  • But Expo’s AppDelegate (in managed workflow) doesn’t implement PKPushRegistryDelegate.

  • There’s no way to inject these methods without ejecting or prebuilding the app.


✅ Expected Behavior

If the required delegate isn’t implemented, the module should fail gracefully instead of crashing the app — or at least log an error.


🧰 Workaround (Only After Ejecting)

Adding this to AppDelegate.mm fixes the crash:

@interface AppDelegate () <PKPushRegistryDelegate> @end

@implementation AppDelegate

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    [RNVoipPushNotificationManager voipRegistration];
    return [super application:application didFinishLaunchingWithOptions:launchOptions];
    }
  • (void)pushRegistry:(PKPushRegistry *)registry
    didUpdatePushCredentials:(PKPushCredentials *)credentials
    forType:(PKPushType)type
    {
    [RNVoipPushNotificationManager didUpdatePushCredentials:credentials forType:type];
    }
  • (void)pushRegistry:(PKPushRegistry *)registry
    didReceiveIncomingPushWithPayload:(PKPushPayload *)payload
    forType:(PKPushType)type
    withCompletionHandler:(
    void (^)(void))completion
    {
    [RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:type];
    completion();
    }
    @end

But this is not possible in the Expo managed workflow (especially for Windows users).


💬 Suggestion

Would it be possible for:

  • react-native-voip-push-notification to detect Expo runtime and skip native delegate registration?

  • Or at least fail gracefully instead of hard-crashing?

  • Or for Expo to officially document PushKit support and how to integrate safely?


📎 Additional Context

  • The crash occurs before any JS logs appear.

  • Same behavior in both dev-client and release TestFlight builds.

  • iOS logs confirm it’s triggered by missing delegate method:

    pushRegistry:didUpdatePushCredentials:forType:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions