React Native {NativeModules} not importing on M1/Silicon mac - returning empty object {}

1k Views Asked by At

I am attempted to create a React-native 'Native Module' (BankedSdk) in a project developed on an M1 Macbook. - However any attempt to initialise the module returns an empty object.

This is the example (2020) repo that works on my intel machine ✅: https://github.com/banked/banked-react-native-sdk-example

On my larger (M1 based) project i have integrated it like this:

Within my iOS folder I have three new files:

BankedSdk.h:

#import <Foundation/Foundation.h>
#import "React/RCTBridge.h"

NS_ASSUME_NONNULL_BEGIN

@interface BankedSdk : NSObject <RCTBridgeModule>

@end

NS_ASSUME_NONNULL_END

BankedSdk.m:

#import "BankedSdk.h"
#import "React/RCTLog.h"
#import "BankedReactNativeExample-Swift.h"

@implementation BankedSdk

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(initialise:(NSString *)apiKey)
{
  [[BankedCheckoutWrapper shared] setUpWithApiKey: apiKey];
}

RCT_EXPORT_METHOD(openBankedSdk:(NSString *)paymentId and:(NSString *)continueUrl)
{
  dispatch_async(dispatch_get_main_queue(), ^{
    UIViewController *presentedViewController = RCTPresentedViewController();
    
    [[BankedCheckoutWrapper shared] presentCheckoutWithViewController: presentedViewController  paymentId: paymentId continueURL: continueUrl];
  });
}

RCT_EXPORT_METHOD(handlePaymentForURL:(NSURL *)url)
{
  [[BankedCheckoutWrapper shared] handlePaymentWithUrl: url];
}

@end

BankedWrapper.swift:

import Foundation
import UIKit
import Banked

@objc class BankedCheckoutWrapper: NSObject {
     
  @objc static let shared: BankedCheckoutWrapper = BankedCheckoutWrapper()
  
  @objc func setUp(apiKey: String) {
    BankedCheckout.shared.setUp(apiKey)
  }
  
  @objc func presentCheckout(viewController: UIViewController ,paymentId: String, continueURL: String) {
    BankedCheckout.shared.presentCheckout(viewController , paymentId: paymentId, action: .pay, continueURL: continueURL) { response in
      switch response {
      case .success:
        print("success")
      case .failure(let error):
        print("error \(error)")
      }
    }
  }
  
  @objc func handlePayment(url: URL) {
    
    BankedCheckout.shared.handlePaymentWithURL(url, action: .pay) { response in
      switch response {
      case .success:
        print("success")
      case .failure(let error):
        print("error \(error)")
      }
    }
  }
}

Then I have a component called Banked Sdk which reads as follows:

import { NativeModules } from 'react-native'

const { BankedSdk } = NativeModules

export default BankedSdk

Which is called as follows:

import React, { useState, useEffect } from 'react'
[import a bunch of other stuff]
import BankedSdk from '@components/BankedSdk'


//Main file stuff
 
// -> TEST NATIVE MODULES BUTTON

  function checkNativeModules() {
    const apiKey = "xxxxxxxxxxxxxxxx"
    BankedSdk.initialise(apiKey)
    BankedSdk.openBankedSdk("xxxxxxxxxxxxxxxx", "urlHere")
   console.log("Banked Sdk in Test Button: ", BankedSdk)
  }




  return (
    <>
     // Other UI stuff
      <Button
       title="Initiate Native Mod"
       color="primary"
       onPress={checkNativeModules}
       />
    </>
  )
}

export default Button

However - My NativeModules are logging out as an empty object:

Native Modules: {}

with the error:

ERROR TypeError: null is not an object (evaluating '_BankedSdk.default.initialise')

(see images)

enter image description here enter image description here

***** UPDATE in response to @user3193920 *****

This was eventually fixed with the following:

in Podfile:

# ENABLES BANKED (DYMANIC FRAMEWORK)
  pod 'Banked', '0.0.25', :build_type => :dynamic_framework 

BankedSdk.h:

#import <Foundation/Foundation.h>
#import "React/RCTBridge.h"

NS_ASSUME_NONNULL_BEGIN

@interface BankedSdk : NSObject <RCTBridgeModule>

@end


NS_ASSUME_NONNULL_END

BankedSdk.m:

#import "BankedSdk.h"
#import "React/RCTLog.h"
#import "systemSpendAppReactNativeOnM1-Swift.h"

@implementation BankedSdk

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(initialise:(NSString *)apiKey)
{
  dispatch_async(dispatch_get_main_queue(), ^{
    [[BankedCheckoutWrapper shared] setUpWithApiKey: apiKey];
  });
}

RCT_EXPORT_METHOD(openBankedSdk:(NSString *)paymentId and:(NSString *)continueUrl and:(RCTPromiseResolveBlock)resolve and:(RCTPromiseRejectBlock)reject)
{
  dispatch_async(dispatch_get_main_queue(), ^{
    UIViewController *presentedViewController = RCTPresentedViewController();

    [[BankedCheckoutWrapper shared] presentCheckoutWithViewController: presentedViewController  paymentId: paymentId continueURL: continueUrl resolve: resolve rejecter: reject];
  });
}

RCT_EXPORT_METHOD(handlePaymentForURL:(NSURL *)url)
{
  dispatch_async(dispatch_get_main_queue(), ^{
    [[BankedCheckoutWrapper shared] handlePaymentWithUrl: url];
  });
}

@end

And BankedWrapper.swift:

import Foundation
import UIKit
import Banked

@objc class BankedCheckoutWrapper: NSObject {

  private var presentingCheckout = false {
    didSet {
      print("+++ presentingCheckout \(presentingCheckout.description)")
    }
  }
  @objc static let shared: BankedCheckoutWrapper = BankedCheckoutWrapper()
  
  @objc func setUp(apiKey: String) {
    BankedCheckout.shared.setUp(apiKey)
  }
  
  @objc func presentCheckout(viewController: UIViewController ,paymentId: String, continueURL: String,  resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
    presentingCheckout = true
    return BankedCheckout.shared.presentCheckout(viewController , paymentId: paymentId, action: .pay, continueURL: continueURL) { [weak self] response in
      guard let self = self else { return }
      if self.presentingCheckout {
        switch response {
        case .success:
          print("+++ success presentCheckout")
          resolve("success")
        case .failure(let error):
          print("+++ error presentCheckout \(error)")
          let errorNew = NSError(domain: "", code: 200, userInfo: nil)
          reject("Caught error", "error", errorNew)
        }
      }
      self.presentingCheckout = false
    }
  }
  
  @objc func handlePayment(url: URL) {
    BankedCheckout.shared.handlePaymentWithURL(url, action: .pay) { response in
      switch response {
      case .success:
        print("+++ success handlePayment")
      case .failure(let error):
        print("+++ error handlePayment \(error)")
      }
    }
  }
}
0

There are 0 best solutions below