Call Swift function from Objective-C class

Objective CSwift

Objective C Problem Overview


I have an old Objective-C project and I want to call new Swift function and object, I have create the file "<ProjectName>-Bridging-Header.h" and "<ProjectName>-Swift.h"

was easy for me call the function from Swift to Objective-C but I have a problem for reverse.

So I have create a simple class "System.Swift"

import Foundation

@objc class System : NSObject {

    @objc func printSome() {
        println("Print line System");
    }
    
}

now I have try to follow the documentation here and inside the <...>-Swift.h file I have write this

@class System;

@interface System : NSObject

-(void)printSome;

@end

and I have import it inside my Objective-C Class. At this point inside my Objective C class (currently UIViewController) of my Objective-C code I have try to call "printSome" method:

- (void)viewDidLoad
{
    [super viewDidLoad];
    System * sis = [[System alloc] init];
    [sis printSome];
    //any additional setup after loading the view from its nib.
}

now I have the following Error:

> Undefined symbols for architecture i386: "OBJC_CLASS$_System", > referenced from: > objc-class-ref in "ObjectiveC_Class_That_Call_Swift_Object".o ld: symbol(s) not found for architecture i386 clang: error: linker > command failed with exit code 1 (use -v to see invocation)

Objective C Solutions


Solution 1 - Objective C

Problem Solved, I previously create and included a new .h file in my Objective-C class named <ProductModuleName>-Swift.h but, as i discovered later, this step is not necessary because the compiler creates the necessary file invisible.

Simply include <ProductModuleName>-Swift.h in your class and it should work.

Solution 2 - Objective C

It is strange but will work after we do:

  1. Add @objc to your Swift-class ("MySwiftClass").

  2. Add in Obj-C, i.e. the .m file:

    #import "(ProjectName)-Swift.h"
    
  3. Declare in header .h

    @class MySwiftClass;
    

Compiler will generate the interface for @objc marked class in MyModuleName-Swift.h file.

Auto-Generated Obj-C Example:

SWIFT_CLASS("_TtC10Project17220PLHelper")
@interface PLHelper

+ (void)notifyForDownloading:(NSDictionary *)userInfo;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

Solution 3 - Objective C

Assume We have ProjectName "MyFirstProjectOnSwift" and swift class name "mySwiftClass" and objectiveC class is "MyObjectiveCLass"

Following steps are:-

> 1. Add #import "MyFirstProjectOnSwift-Swift.h" in "MyObjectiveCLass.m" > > 2. Add @class mySwiftClass in MyObjectiveCLass.h; > > 3. Then in MyObjectiveCLass.m > > mySwiftClass *myClass = [mySwiftClass new]; {Call Like This in any > method wherever you want to call swift method.} > > 4. [myClass methodName];

Solution 4 - Objective C

Check the -Swift.h file which has the import on your .m file in objective-C:

#import <YourProjectName-Swift.h>

Click on that line, and left-click - Jump To Definition.

This file should be included automatically, not manually.

Solution 5 - Objective C

Little additional tip for anyone stumbling upon this post and for hwhom the other answers do not work: you might also have to declare your Swift class "public".

Example:

@objc public class MySwiftClass: NSObject {

Solution 6 - Objective C

If you're still not seeing your class even after importing <ProductModuleName>-Swift.h.

Make sure that your class is subclassing a native class (e.g UIViewController) or at least if it's just a utility class, make it subclass NSObject. Your class should now show.

Solution 7 - Objective C

The recomended way for executing Swift code from Objective-C on projects that are being migrated from Obj-C to Swift is using Bridge/Proxy pattern.

  1. Implement the Bridge.

import Foundation

@objc class AnalyticsPropertyBridge: NSObject {

private var analytics: AnalyticsManager = AnalyticsManager()

@objc func refreshProperties() {

    self.analytics.set(AnalyticsProperty.clientType)
}

}

  1. Include the objC caller module in the umbrella file (Bridging-Header):

#import "CallerModule.h"

  1. Finally in the caller .m file, two issues:

3.a Import umbrella file:

#import "MyProject-Swift.h"

3.b Call the bridge.

[[AnalyticsPropertyBridge new] refreshProperties];

Benefits: Your swift code will not get dirty with @objc because code is being called from Objc. As time goes by, the ObjC will be reduced in your project and finally the bride will be removed.

Solution 8 - Objective C

A note about project name, if there are spaces in project name make sure you replace them with underscore, for example if project name is "My Project" you need to include:

#import <My_Project-Swift.h>

Solution 9 - Objective C

A good article out here if someone still having issues.

Setting up Swift and Objective-C Interoperability

  1. This article discusses in-depth how to import Swift files into ObjC as well as Objc files to Swift.
  2. It also addresses a problem generally faced when the Project name has space in it.
  3. It also discusses about “Product Module Name” flag.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEloredenView Question on Stackoverflow
Solution 1 - Objective CEloredenView Answer on Stackoverflow
Solution 2 - Objective CSvitlanaView Answer on Stackoverflow
Solution 3 - Objective CAnubhav GiriView Answer on Stackoverflow
Solution 4 - Objective CDarius MiliauskasView Answer on Stackoverflow
Solution 5 - Objective CKqtrView Answer on Stackoverflow
Solution 6 - Objective CBryan PView Answer on Stackoverflow
Solution 7 - Objective CJavier Calatrava LlaveríaView Answer on Stackoverflow
Solution 8 - Objective CFarhad MalekpourView Answer on Stackoverflow
Solution 9 - Objective CTridentView Answer on Stackoverflow