Benjamin Netter
Benjamin Netter

Reputation: 1551

Got "is not a recognized Objective-C method" when bridging Swift to React-Native

I'm trying to bridge my React-Native 0.33 code to a super simple Swift method, following this guide but all I'm getting is show:(NSString *)name is not a recognized Objective-C method.

Here's my code:

SwitchManager.swift

import Foundation

@objc(SwitchManager)
class SwitchManager: NSObject {

  @objc func show(name: String) -> Void {
    NSLog("%@", name);
  }

}

SwitchManagerBridge.h

#import "RCTBridgeModule.h"

@interface RCT_EXTERN_MODULE(SwitchManager, NSObject)

RCT_EXTERN_METHOD(show:(NSString *)name)

@end

SwitchManager-Bridging-Header.h

#import "RCTBridgeModule.h"

Then on my index.ios.js file I'm importing SwitchManager with import { SwitchManager } from 'NativeModules'; and calling SwitchManager.show('One');. This is where the error happened.

Not sure what's wrong.

Upvotes: 44

Views: 18657

Answers (5)

Rebs
Rebs

Reputation: 312

If you have multiple parameters you have these options:

1. If you DON'T want to use parameter labels:

Objective-C:

RCT_EXTERN_METHOD(
  addEvent
    :(NSDictionary *) event
    :(RCTPromiseResolveBlock) resolve
    :(RCTPromiseRejectBlock) reject
)

Swift Option 1:

  @objc
  func addEvent(
    _ event: NSDictionary,
    _ resolve: RCTPromiseResolveBlock,
    _ reject: RCTPromiseRejectBlock
  ) {...}

Swift Option 2:

  @objc(addEvent:::)
  func addEvent(
    event: NSDictionary,
    resolve: RCTPromiseResolveBlock,
    reject: RCTPromiseRejectBlock
  ) {...}

2. If you want to use parameter labels:

Objective-C:

RCT_EXTERN_METHOD(
  addEvent
    :(NSDictionary *) event
    rejecter :(RCTPromiseResolveBlock) resolve
    resolver :(RCTPromiseRejectBlock) reject
)

Swift:

  @objc
  func addEvent(
    _ event: NSDictionary,
    resolver resolve: RCTPromiseResolveBlock,
    rejecter reject: RCTPromiseRejectBlock
  ) {...}

Coming from JavaScript, Java and now programming React Native Modules, I think these labels do more harm then good, especially that the first label can't be set. Now everybody learning Objective C will wonder and hard learn this. At least they are optional in Objective C, but if you combine it with Swift it gets crazy again. Because everything does not make sense, I've tested every possible variation in XCode 15. I've lost at least two days on this and I hope it helps someone.

Upvotes: 1

Raphael Pinel
Raphael Pinel

Reputation: 2780

I had the same error because I had forgotten to put the decorator @objc before the function declaration

Upvotes: 2

James Wang
James Wang

Reputation: 1311

This is a part of Swift 3's changes and can be solved by adding an underscore:

import Foundation

@objc(SwitchManager)
class SwitchManager: NSObject {

  @objc func show(_ name: String) {
    NSLog("%@", name);
  }

}

See Swift 3's 0046 Proposal: Establish consistent label behavior across all parameters including first labels that is called out in the Swift.org migration guide under "Consistent first argument labels".

Basically, how Objective-C sees Swift methods has changed with Swift 3.

EDIT: This is still the case in Swift 4, see docs here under Omitting Argument Labels.

Upvotes: 82

Vijesh Krishna
Vijesh Krishna

Reputation: 449

this worked for me in xcode 8.0 and swift 3

@objc func openPresentedViewController(_ name: String,name1: String,name2: String){
}

add _ to non labelled members

RCT_EXTERN_METHOD(methodName:(NSString *)name name1:(NSString *)name1 name2:(NSString *)name2)

as you can see in the objective c method name is nonlabeled parameter add _ to it in the swift method

Upvotes: 23

designbuildplay
designbuildplay

Reputation: 67

I was fighting with this issue all day. Resolved by setting the Swift Compiler to use Legacy versions (XCode 8 is prefers Swift 3), so in:

Build Settings > Scroll down to 'Use Legacy Swift Language Version' set as Yes.

Upvotes: 3

Related Questions