带有异步函数抛出的 Swift 中的 React-Native 模块不是公认的 Objective-C 方法

Chr*_*ant 6 javascript objective-c reactjs swift react-native

我正在尝试根据react-native的文档导出一个swift模块,但是当我尝试在我的javascript文件中调用此函数时遇到以下错误。我相信这个问题与在我的快速代码中调用方法有关async。所以我不确定async在react-native中创建本机模块时如何从我的swift文件导出和调用方法。

异常错误object-c方法

这是 AppleMusicAuth.swift 文件,其中包含async我尝试导出的方法

//
//  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)
  }
}

Run Code Online (Sandbox Code Playgroud)

以及我的 AppleMusicAuth.m 文件,该文件使用将RCT_EXTERN_METHOD模块导出到我的 JS 应用程序的方法

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

#import <Foundation/Foundation.h>

#import <React/RCTBridgeModule.h>


@interface RCT_EXTERN_MODULE(AppleMusicAuth, NSObject)

RCT_EXTERN_METHOD(getAuthStatus)

@end
Run Code Online (Sandbox Code Playgroud)

以及导入和调用使用的模块和方法的Javascript文件

import { NativeModules } from 'react-native';
const { AppleMusicAuth } = NativeModules;
export default AppleMusicAuth;
Run Code Online (Sandbox Code Playgroud)
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;

Run Code Online (Sandbox Code Playgroud)

Osa*_*rem 5

编辑:截至 2023 年 1 月 10 日,我的建议是使用 expo-modules-core,因为它支持此用例。

请参阅: https: //docs.expo.dev/modules/get-started/

示例: https: //github.com/expo/expo/pull/20645

原答案

我刚刚遇到这个问题,这是我的解决方法。我们可以导出一个async常规函数,然后调用该函数,而不是将函数导出到 React Native/Objective-C async

  • 要从 Swift 中的普通函数调用异步函数,我们可以使用Task
  • 要将结果发送回 React Native,我们可以使用事件
  func myAsyncFunction(_ data: NSDictionary) async -> Void {
    // Processing...
    self.sendEvent(withName: "MyEvent", body: "The result")
  }

  @objc
  func myExportedFunction(_ data: NSDictionary) -> Void {
    Task {
      await myAsyncFunction(data)
    }
  }
Run Code Online (Sandbox Code Playgroud)

  • 我想补充一点,“async”不适用于 React Native 的原因是该函数在 Objective-C 中添加了一个完成处理程序。我们可以在 Objective-C 中导入 `#import &lt;Product_NAME-Swift.h&gt;` 标头来查看可用的内容。如果您打开该头文件,您会发现您的“async”方法已添加了桥不支持的完成处理程序。 (2认同)
  • 救命的答案,谢谢!我还能够使用 RCTResponseSenderBlock 类型的回调将结果发送回 React Native,如 RN 文档中所述。它只需在导出的(非异步)函数中声明为 @escaping 即可。 (2认同)