5

I followed the guide here to create a turbo module. This was fine.

https://reactnative.dev/docs/the-new-architecture/pillars-turbomodules

I want to use Swift code in this turbo module. I tried adding a Swift file with this code and modifying the RTNCalculator.mm so that the number addition happens in Swift called from Objective-C.

SwiftCalculator.swift

import Foundation

@objc class SwiftCalculator: NSObject {
    @objc func add(a: Double, b: Double) -> Double {
        return a + b
    }
}

RTNCalculator.mm

#import "RTNCalculatorSpec.h"
#import "RTNCalculator.h"
#import "RTNCalculator-Swift.h"

@implementation RTNCalculator

RCT_EXPORT_MODULE()

- (void)add:(double)a b:(double)b resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
    SwiftCalculator *calculator = [SwiftCalculator new];
    double value = [calculator addWithA:a b:b];
    NSNumber *result = [[NSNumber alloc] initWithDouble:value];
    resolve(result);
}

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
    (const facebook::react::ObjCTurboModule::InitParams &)params
{
    return std::make_shared<facebook::react::NativeCalculatorSpecJSI>(params);
}

@end

I also modified the pod spec file to use a bridging header file.

  s.pod_target_xcconfig = { 
    'SWIFT_OBJC_BRIDGING_HEADER' => '../../node_modules/rtn-calculator/ios/RTNCalculator-Bridging-Header.h'
  }

This doesn't work. I get this error in the project.

Using bridging headers with framework targets is unsupported

How do I use Swift in a Turbo Module?

Berry Blue
  • 15,330
  • 18
  • 62
  • 113

2 Answers2

0

For your example, you shouldn't need a bridging header at all. That allows you to import ObjC into Swift, not Swift into ObjC. Did you try just removing the SWIFT_OBJC_BRIDGING_HEADER bit?

The RTNCalculator-Swift.h header is what lets you import Swift into ObjC, and that part of of your code looks ok. What specific error do you receive if you take out the bridging header?

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • If I try that I'm getting this error. It goes away if I delete the Swift file. `RTNCalculatorSpec.h:15:2 This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.` – Berry Blue May 18 '23 at 17:47
0

To resolve the issue for your Cocoa Pod (Turbo Module) you should make the following:

  1. Mark @objc and public all needed classes, method, properties etc. in your swift code because all of them are internal by default and are not visible outside.
@objc
public class SwiftCalculator: NSObject {
    @objc
    public func add(a: Double, b: Double) -> Double {
        a + b
    }
}
  1. Import the pod's swift/objc generated header into your obj files in the format: "<MyPodName>+Swift.h". In your case the pod name is "rtn_calculator".
...
#import "rtn_calculator-Swift.h"
...
RCT_REMAP_BLOCKING_SYNCHRONOUS_METHOD(add, NSNumber*, addA:(NSInteger)a andB:(NSInteger)b)
{
    SwiftCalculator* calculator = [SwiftCalculator new];
    double value = [calculator addWithA:a b:b];
    return @(value);
}
iUrii
  • 11,742
  • 1
  • 33
  • 48
  • 1
    The header file seems to be picked up but it's not finding my Swift class. `Unknown type name 'SwiftCalculator'; did you mean 'RTNCalculator'?` – Berry Blue May 18 '23 at 17:51
  • @BerryBlue The Header file name must contain the name of your pod in a podspec file: s.name = "rtn-calculator" and a name of your class must be the same. – iUrii May 18 '23 at 18:31
  • Yes, the name is "rtn-calculator". – Berry Blue May 18 '23 at 19:03
  • How do I check that it's generating the header properly? – Berry Blue May 18 '23 at 19:03
  • I'm also getting this error about my Swift file so I think I still need to add a configuration somewhere. `RTNCalculatorSpec.h:15:2 This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.` – Berry Blue May 18 '23 at 19:05