Call Swift function from Objective-C class
Objective CSwiftObjective 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:
-
Add
@objc
to your Swift-class ("MySwiftClass
"). -
Add in Obj-C, i.e. the
.m
file:#import "(ProjectName)-Swift.h"
-
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.
- Implement the Bridge.
import Foundation
@objc class AnalyticsPropertyBridge: NSObject {
private var analytics: AnalyticsManager = AnalyticsManager()
@objc func refreshProperties() {
self.analytics.set(AnalyticsProperty.clientType)
}
}
- Include the objC caller module in the umbrella file (Bridging-Header):
#import "CallerModule.h"
- 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
- This article discusses in-depth how to import Swift files into ObjC as well as Objc files to Swift.
- It also addresses a problem generally faced when the Project name has space in it.
- It also discusses about “Product Module Name” flag.