40

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.

Benjamin Netter
  • 1,501
  • 3
  • 18
  • 34

4 Answers4

79

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.

James Wang
  • 1,281
  • 9
  • 17
  • 1
    This did it for me. I can confirm this is working with Swift 3 and React Native 0.34.0-rc.0. – Mike Cole Oct 04 '16 at 17:47
  • 2
    Another note on this: my method has 3 parameters and so I added the underscore for each of them. This did not work! You must add it to _only_ the non-labeled parameters – John kendall Oct 13 '16 at 15:48
  • Yup, the main goal if you look at the docs is to keep compatibility with Obj-C libraries. Apple is likely going to be trying to phase this out entirely over time—in fact, swift-only functions don't require this underscore behavior. Reason why it comes up here is React Native is all Obj-C. – James Wang Oct 18 '16 at 18:46
  • 2
    excellent! whats going on with that weird underscore? can someone shed some light? – Yaron Levi Feb 20 '17 at 23:45
  • See the link I put above for Apple's 0046 Proposal. It's basically because Objective C can have unnamed first arguments, but Swift now has named first arguments across the board. This underscore just keeps compatibility with existing libraries by having an explicit "unnamed" argument. – James Wang Feb 21 '17 at 03:44
  • This also works for me. React native version 0.46.0 and swift 3, xcode 8.3. – riyaz Jul 20 '17 at 10:19
  • Yup... if it matters, confirmed still working for me in my production app code underneath a React Native app. It's not an issue with RN regardless, since this is a Swift 3 standard. Confirmed, btw, that this will continue to be the case in Swift 4: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html – James Wang Aug 09 '17 at 22:22
  • 1
    tnx, it works. it is still a case in Swift4 and xcode 9.4.1 – Leon Jul 13 '18 at 05:30
  • Awesome Thanks – Tom Oct 16 '18 at 12:38
  • May be a different error, @Kartiikeya? At least for this specific issue, seems to still be necessary/the case for my code. – James Wang Feb 25 '19 at 20:08
  • @GeorgeSalamanca Yes? This is now pretty fundamentally in Swift. If anything, it's more relevant given the changes in Swift 4 (though this matters more for native code): https://stackoverflow.com/questions/44379348/the-use-of-swift-3-objc-inference-in-swift-4-mode-is-deprecated. One day, it won't be when React Native itself is written in swift, but until then... – James Wang May 13 '19 at 18:38
22

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

Koen.
  • 25,449
  • 7
  • 83
  • 78
Vijesh Krishna
  • 439
  • 3
  • 9
3

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.

  • Does this mean you can't use Swift 3? I'm running into this issue as well, but I would like to use Swift 3 if possible. – Mike Cole Oct 03 '16 at 00:47
  • 1
    @mike-cole Take a look at below. If you've been having trouble, see if the underscore makes a difference since that's a change in Swift 3 for compatibility with ObjC methods. It isn't the cause of everyone's problems (I landed here due to a different "is not a recognized Objective-C method" issue), but I'd guess this is a common one. – James Wang Oct 03 '16 at 21:56
  • 7
    This shouldn't be the accepted answer, this is just a workaround. The solutions below about method labels are the actual solution to the problem. – Koen. Jul 01 '17 at 17:39
2

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

Raphael Pinel
  • 2,352
  • 24
  • 26