100

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)

6
  • You have a linker error. Is it: (1) Xcode uses your product module name—not your target name—when naming the Objective-C bridging header and the generated header for your Swift code, or (2) make sure to import the Objective-C headers for those types prior to importing the Swift generated header into the Objective-C .m file you want to access the Swift code from? Do you have: #import “ProductModuleName-Swift.h” in your Objective-C code? Commented Jun 6, 2014 at 9:25
  • Yes i have read the documentation and the name of "ProductModelName" is currect... There is a bug that inside the Build Setting the Product model was not set... i have even set it... Commented Jun 6, 2014 at 9:39
  • @petert can you explain better the second point? I wrote everithing i did... Commented Jun 6, 2014 at 10:11
  • Problem Solved, i have add a new .h file in my project call <ProductModelName>-Swift.h but this is not necessary because the compiler just create this object even if i can't see it. I have delete the new file that i have create and now all run perfectly. Tnx petert Commented Jun 6, 2014 at 10:46
  • You can answer your own questions - it might help others. Commented Jun 6, 2014 at 15:24

9 Answers 9

68

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
Sign up to request clarification or add additional context in comments.

6 Comments

You can also override the Obj-C name of your Swift class using @objc (MyClassName)
For anyone who may do same dumb mistake as me. In step 2, make sure you use (ProjectName)-Swift.h, NOT (ClassName)-Swift.h !
thanks @Svitlana, unbelievable, it worked!!! But I have to retry many times these steps, including moving my added methods to other places in the class.
3) @class SwiftClassName; saved me
if your target name has any spaces add "_" (underscores instead of spaces) when creating swift.h import eg: if your target name is Sample App then your import statement would be #import "Sample_App-Swift.h"
|
63

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.

6 Comments

how about functions with parameters?
I am not able to access Swift functions with parameters and a return value, nor I am able to access Swift Functions without parameters and without a return value. I don't know why. My Swift Class is an NSObject, I imported the Foundation framework, the class and the functions have the @objc prefix. The -Swift.h has been automatically created. The thing that is making me headache is that I can call the Class itself but not any function inside it. Does anyone know why?
It is <productModuleName>-.Swift.h (not model).
If your Product name has any spaces in it, replace them with underscores, like: #import "My_Project-Swift.h".
|
36

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];

2 Comments

mySwiftClass *myClass = [mySwiftClass new] its not working for me>>>>>
@HariNarayanan It should not be, do one think clear derived data and reopen your project.
13

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.

1 Comment

My project name had a space in it; which looks like xcode replaced with an underscore for this file name. But if you type the < left angle bracket after the #import statement, and start typing your project name - you'll likely see the correct .h file listed in xcode's code completion popup.
7

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 {

Comments

2

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.

Comments

0

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.

Comments

0

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>

Comments

-3

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.

1 Comment

Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.