Search code examples
iosobjective-cswiftios-frameworksobjective-c-swift-bridge

"No visible @interface for 'MySwiftFile' declares the selector '****'" in iOS framework


I've been having trouble with using Swift in an ObjC framework in iOS. My framework has Objective-C code, which I want to call Swift code from.

I think I have created the bridging properly, I'll show below what I've done.

MySwiftFile.swift :

open class MySwiftFile: NSObject {
  var varDummy : RandomType? = nil
  open func setupDummy(param1 : RandomType1) {
    varDummy = RandomType(p: param1)
  }
}

MyObjCFile.m :

@class MySwiftFile;
#import "MyFramework/MyFramework-Swift.h"

@interface A : NSObject<...>
@property(atomic) MySwiftFile *mySwiftFile;

.....
@end
@implementation Aclass
......
@end

@interface B ()
....
@property(readonly, nonatomic) A *refA;
@end

@implementation B
....
- (void)methodCalledSomewhere:(RandomType1 *)type {
   ....
   refA.mySwiftFile = [[MySwiftFile alloc] init];
   [refA.mySwiftFile setupDummy: type];   <====THIS LINE PRODUCES THE ERROR
}
....

To sum it up, I want to init the property and call a function of a Swift object from ObjC code. Xcode seems to recognize MySwiftFile as a valid type, then how come it does not allow me to call the "setupDummy" method?

The errors are 2:

  • No visible @interface for 'MySwiftFile' declares the selector 'setupDummy:'
  • No visible @interface for 'MySwiftFile' declares the selector 'setupDummy'

Solution

  • First problem is that you forget to expose it to the Objective-C. Either add @objcMembers to expose everything ...

    @objcMembers
    open class MySwiftFile: NSObject {
        ...
    }
    

    ... or just add @objc to your setupDummy function ...

    @objc
    open func setupDummy(param1: String) {
        ...
    }
    

    Second problem is about how the function name is translated to Objective-C ...

    • @objc func setupDummy(param1 : RandomType1) -> setupDummyWithParam1:
    • @objc func setupDummy(_ param1: RandomType1) -> setupDummy:
    • @objc(setupDummy:) func setupDummy(param1: String) -> setupDummy:

    ... which means that adding just @objc wont work. You have to either change the Swift function signature or use setupDummyWithParam1: in your Objective-C or keep the Swift function signature & use @objc(<name>) to change the Objective-C selector.