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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions