Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

swift 3 method in objective-c fails with no visible @interface for 'MySwiftClass' declares the selector 'addX:andY'

We are trying to reference Swift methods inside an Objective-C implementation.

Swift class:

import Foundation
@objc class MySwiftClass: NSObject {
    override init() {
        super.init()
    }

    func sayHello() -> Void {
        print("hello");
    }

    func addX(x:Int, andY y:Int) -> Int {
     return x+y
    }
}

Objective-C implementation (Objective-c.m):

#import "ProductModuleName-Swift.h"
MySwiftClass* getData = [[MySwiftClass alloc]init];
[getData sayHello] //works
[getData addX:5 addY:5] //No visible @interface for 'MySwiftClass' declares selector 'addX:addY'

The last line of code gives the following error:

No visible @interface for 'MySwiftClass' declares selector 'addX:addY'

like image 506
complexi Avatar asked Dec 10 '16 20:12

complexi


3 Answers

If you command-click on "ProductModuleName-Swift.h" in the Xcode source file editor then you can see how the Swift methods are mapped to Objective-C.

In your case that would be

@interface MySwiftClass : NSObject - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; - (void)sayHello; - (NSInteger)addXWithX:(NSInteger)x andY:(NSInteger)y; @end 

which is called as

MySwiftClass* getData = [[MySwiftClass alloc]init]; [getData sayHello]; NSInteger result = [getData addXWithX:5 andY:5]; 

A better Swift 3 method name might be

func add(x: Int, y:Int) -> Int 

because x is already the argument (external) name of the first parameter. You can also add an @objc() attribute to the Swift definition to control the Objective-C name. For example, with

@objc(addX:andY:) func add(x: Int, y: Int) -> Int {     return x+y } 

it would be called from Objective-C as

NSInteger result = [getData addX:5 andY:5]; 
like image 66
Martin R Avatar answered Sep 17 '22 13:09

Martin R


As @ekscrypto pointed out, in Swift 4 and later you need to annotate individual functions with @objc. Prior to that, a single, class-level @objc was enough. Of course in Objective-C class you must add import of NAME_PROJECT-swift.h. If your project name is Sample then you must add:

#import Sample-swift.h 

And then:

Swift 4 or Less

@objc class MySwiftClass: NSObject {          func sayHello(){       //function     }      func addX(){       //function     } } 

Swift 4 or Greater

@objc class MySwiftClass: NSObject {          @objc func sayHello(){       //function     }      @objc func addX(){       //function     } } 
like image 36
Jose Pose S Avatar answered Sep 21 '22 13:09

Jose Pose S


In my case I had forgotten to add:

#import "MyProject-Swift.h"

Into the obj c file.

like image 29
lewis Avatar answered Sep 20 '22 13:09

lewis