React-Native Module in Swift with async function throws is not a recognized Objective-C method

Viewed 196

I am trying to export a swift module according to react-native's documentation but I run into the following error when I try to call this function in my javascript file. I believe the issue has to do with calling an async method in my swift code. So I'm not sure how to export and call an async method from my swift file when creating a native module in react-native.

exception error object-c methor

Here is the AppleMusicAuth.swift file that contains the async method I'm trying to export

//
//  AppleMusicAuth.swift
//
//
//

import Foundation
import MusicKit

@available(iOS 15.0, *)
@objc(AppleMusicAuth)
class AppleMusicAuth: NSObject {

  @objc
  func getAuthStatus() async -> Void {
    let response = await MusicAuthorization.request()
    print(response)
  }
}

Along with my AppleMusicAuth.m file that makes use of RCT_EXTERN_METHOD method for exporting the module to my JS application

//
//  AppleMusicAuth.m
//
//
//

#import <Foundation/Foundation.h>

#import <React/RCTBridgeModule.h>


@interface RCT_EXTERN_MODULE(AppleMusicAuth, NSObject)

RCT_EXTERN_METHOD(getAuthStatus)

@end

And the Javascript files that import and call the module and method for use

import { NativeModules } from 'react-native';
const { AppleMusicAuth } = NativeModules;
export default AppleMusicAuth;
import React from 'react';
import {Button} from 'react-native';
import AppleMusicAuth from '../nativeModules/AppleMusicAuth';

type Props = {};

const App: React.FC<Props> = () => {
  return (
        <Button
          onPress={() => {
            AppleMusicAuth.getAuthStatus();
          }}
          title="Button"
          color="#841584"
        />
  );
};

export default App;

1 Answers

I just ran into this, here is my workaround. Instead of exporting an async function to React Native/Objective-C, we can export a regular function which then calls the async one.

  • To call an async function from a normal function in Swift we can use Task
  • To send the result back to React Native we can use events.
  func myAsyncFunction(_ data: NSDictionary) async -> Void {
    // Processing...
    self.sendEvent(withName: "MyEvent", body: "The result")
  }

  @objc
  func myExportedFunction(_ data: NSDictionary) -> Void {
    Task {
      await myAsyncFunction(data)
    }
  }
Related