如何将React Native Promise与Swift联系起来

时间:2022-09-04 10:05:43

Hi fellow software enthousiasts,

嗨其他软件enthousiasts,

I am currently working on a React native project for which I need to add some logic which has been written in swift. I am able to trigger a basic swift function through the bridging to Objective C an then to Swift.

我目前正在研究一个React本机项目,我需要添加一些用swift编写的逻辑。我能够通过桥接到Objective C然后到Swift来触发一个基本的swift函数。

The problem occurs when I try to do something with promises. The page I describing this is clear on the Objective C part for Promises and also for bridging to Swift, but not so on promises to swift: https://facebook.github.io/react-native/docs/native-modules-ios.html

当我尝试用promises做某事时会出现问题。我描述的这个页面在Promise的Objective C部分以及与Swift的桥接上是清楚的,但对于swift的承诺却不是这样:https://facebook.github.io/react-native/docs/native-modules-ios html的

This is what I have:

这就是我所拥有的:

Project-Bridging-Header.h

项目桥接,Header.h

#import <React/RCTBridgeModule.h>

MyLoginBridge.m

MyLoginBridge.m

#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_REMAP_MODULE(MyCustomLoginJSName, MyLoginModule, NSObject)

RCT_EXTERN_REMAP_METHOD(loginWithEmail,
                    resolver:(RCTPromiseResolveBlock)resolve
                    rejecter:(RCTPromiseRejectBlock)reject)

RCT_EXTERN_METHOD(testMethod)

@end

MyLoginModule.swift

MyLoginModule.swift

import Foundation

@objc(TripleASDKModule)
class TripleASDKModule: NSObject {

  @objc
  func loginWithEmail(resolver resolve: RCTPromiseResolveBlock,  rejecter reject: RCTPromiseRejectBlock) -> Void {
    resolve("This method is troublesome")
  }

  @objc func testMethod() -> Void {
    print("This Does appear")
  }
}

When i trigger the testMethod, the print is shown in Xcode, so that swift code is executed. But when I call the loginWithEmail method, I get the infamous red React Native error screen saying:

当我触发testMethod时,打印显示在Xcode中,以便执行快速代码。但是当我调用loginWithEmail方法时,我得到臭名昭着的红色React Native错误屏幕说:

Exception 'resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject is not a recognized Objective-C method.' was thrown while invoking loginWithEmail on target MyCustomLoginJSName with params (
    30,
    31
)

And for the sake of completeness, the Javascript side:

为了完整起见,Javascript方面:

const loginWithEmail = () => NativeModules.TripleA.loginWithEmail()
    .then(result => console.log(result));

I tried almost all variations of RCT_EXTERN_REMAP_METHOD and the like I could find, both with and without Remapping repeating the name, etc. So if this problem sound familiar, or you could guide me in the right direction, please do so, any help is appreciated.

我尝试了RCT_EXTERN_REMAP_METHOD的几乎所有变体以及我能找到的,有和没有重复重复名称的等等。所以,如果这个问题听起来很熟悉,或者你可以指导我正确的方向,请这样做,任何帮助表示赞赏。

3 个解决方案

#1


6  

Taken from the answers at Got "is not a recognized Objective-C method" when bridging Swift to React-Native; the fact that it doesn't work, is because of the difference in the first argument labels.

当将Swift与React-Native连接起来时,取自Got的答案“不是公认的Objective-C方法”;它不起作用的事实是因为第一个参数标签的不同。

To make it work with your initial code you should write your Swift method like this:

要使它与您的初始代码一起使用,您应该像这样编写Swift方法:

@objc
func loginWithEmail(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
    //   the trick  ^
    resolve("This method is no longer troublesome")
}

#2


1  

Adding so that the complete solution is shown

添加以便显示完整的解决方案

.m - note that the resolve parameter is not "named"

.m - 请注意,resolve参数不是“命名”

RCT_EXTERN_METHOD(loginWithEmail: (RCTPromiseResolveBlock)resolve
                                  rejecter:(RCTPromiseRejectBlock)reject)

.swift - same as @Koen

.swift - 和@Koen一样

@objc func loginWithEmail(_ resolve: @escaping RCTPromiseResolveBlock,
                            rejecter reject: @escaping RCTPromiseRejectBlock ) -> Void {}

#3


0  

I did eventually come up with a solution. It is not exactly like React native people intended it I believe, but it works. So i can continue and maybe someone else is set on the right track with my solution. Although, please post the way it is supposed to be.

我最终想出了一个解决方案。它并不完全像我认为的React原住民意图,但它的确有效。所以我可以继续,也许其他人与我的解决方案在正确的轨道上。虽然,请按照预期的方式发布。

So I decided to start with the Objective-C way first. So I created a .h file for my module.

所以我决定先从Objective-C方式开始。所以我为我的模块创建了一个.h文件。

MyLoginBridge.h

MyLoginBridge.h

#import <React/RCTBridgeModule.h>

@interface MyLoginBridge : NSObject <RCTBridgeModule>
@end

Then alter the .m file

然后更改.m文件

#import "MyLoginBridge.h"
#import "MyProject-Swift.h" // Include the swift header manually

@implementation MyLoginBridge

RCT_EXPORT_MODULE(MyCustomLoginJSName);

RCT_EXPORT_METHOD(loginWithEmail:(RCTPromiseResolveBlock)resolve   rejecter:(RCTPromiseRejectBlock)reject)
{
    // Manually init the module and call swift function
    MyLoginModule* module = [[MyLoginModule alloc] init];
    [module loginWithEmailWithResolver:resolve rejecter:reject];
}

@end

The swift file and the bridging header remained the same. This works.

swift文件和桥接头保持不变。这很有效。

#1


6  

Taken from the answers at Got "is not a recognized Objective-C method" when bridging Swift to React-Native; the fact that it doesn't work, is because of the difference in the first argument labels.

当将Swift与React-Native连接起来时,取自Got的答案“不是公认的Objective-C方法”;它不起作用的事实是因为第一个参数标签的不同。

To make it work with your initial code you should write your Swift method like this:

要使它与您的初始代码一起使用,您应该像这样编写Swift方法:

@objc
func loginWithEmail(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
    //   the trick  ^
    resolve("This method is no longer troublesome")
}

#2


1  

Adding so that the complete solution is shown

添加以便显示完整的解决方案

.m - note that the resolve parameter is not "named"

.m - 请注意,resolve参数不是“命名”

RCT_EXTERN_METHOD(loginWithEmail: (RCTPromiseResolveBlock)resolve
                                  rejecter:(RCTPromiseRejectBlock)reject)

.swift - same as @Koen

.swift - 和@Koen一样

@objc func loginWithEmail(_ resolve: @escaping RCTPromiseResolveBlock,
                            rejecter reject: @escaping RCTPromiseRejectBlock ) -> Void {}

#3


0  

I did eventually come up with a solution. It is not exactly like React native people intended it I believe, but it works. So i can continue and maybe someone else is set on the right track with my solution. Although, please post the way it is supposed to be.

我最终想出了一个解决方案。它并不完全像我认为的React原住民意图,但它的确有效。所以我可以继续,也许其他人与我的解决方案在正确的轨道上。虽然,请按照预期的方式发布。

So I decided to start with the Objective-C way first. So I created a .h file for my module.

所以我决定先从Objective-C方式开始。所以我为我的模块创建了一个.h文件。

MyLoginBridge.h

MyLoginBridge.h

#import <React/RCTBridgeModule.h>

@interface MyLoginBridge : NSObject <RCTBridgeModule>
@end

Then alter the .m file

然后更改.m文件

#import "MyLoginBridge.h"
#import "MyProject-Swift.h" // Include the swift header manually

@implementation MyLoginBridge

RCT_EXPORT_MODULE(MyCustomLoginJSName);

RCT_EXPORT_METHOD(loginWithEmail:(RCTPromiseResolveBlock)resolve   rejecter:(RCTPromiseRejectBlock)reject)
{
    // Manually init the module and call swift function
    MyLoginModule* module = [[MyLoginModule alloc] init];
    [module loginWithEmailWithResolver:resolve rejecter:reject];
}

@end

The swift file and the bridging header remained the same. This works.

swift文件和桥接头保持不变。这很有效。