Skip to main content

Using Swift with Objective-C and Cocoa

Swift gain so much popularity in very short duration and people are really very excited to develop the application in swift. So, the number of application in swift is increasing exponentially. However, there are vast numbers of legacy applications which are built using objective-c and now in the process of migration or mixture (Objective-C & Swift).

Today, I will explain how to integrate swift in the existing Objective-c application and vice versa.

Let suppose you are working on an application written totally in objective-c and now you want to implement all the new feature in swift then you can follow the following steps to use both the languages in a single application:

Access Swift Class into Objective-C

1) Add a new swift file in your application by selecting File ->  New->File. Then select a swift file as an option.
2) As you click on "Create", a dialogue box will appear which give you an option to create a bridging Header. Make sure to select Create Bridging Header”. 




Note: Dialogue box appears only once when you add a swift file first time. If by mistake you have chosen other option like "Cancel" or "Don't Create" then you can follow a manual process to add bridge file.

3) Check for “Product Module Name” in the build settings of the application. If you have not change it manually then it should match with your product name. Write the product module name somewhere.



4) Next, open the objective-c class where you want to access the swift object or class. import the file name in the format “Product Module Name-swift.h” in the implementation file of the objective-c class.

Let suppose your product module name is "test", then Xcode will generate a swift interface file with the name (test-Swift.h) and your import statement should be like following:


#import "test-Swift.h"

What if You are still not able to access swift class or its members?

If it happening to you, It might be because you cannot access swift type like Swift Struct, Swift enum in objective-c. However, you can access the class and protocol written in swift by making it compatible with objective-c.

To make a swift class compatible with objective-c you just need to inherit that class from NSObject:


class SwiftTest:NSObject{
    func printFromObjectiveC(){
        print("printFromObjectiveC")
    }
}
//In Objective-C Class
SwiftTest *testFromObjectiveC= [[SwiftTest alloc] init];
[testFromObjectiveC printFromObjectiveC];

To make a swift protocol compatible with objective-c you have to add @objc before the protocol declaration and this will make your protocol visible in objective-c. 


@objc protocol SwiftNObjective{
    func test1()
}

You can add @objc before the class declaration also but it should be inherited from NSObject.

Hurray !!! Hurdle 1 Completed. Now, you can use swift class in objective-c. 

Note: While adding @objc keyword before class or protocol if you get any error then might be your class is using purely swift data type like swift enum or swift struct which is not accessible or bridged to objective-c.

Access Objective-C Class into Swift

Now let's go to Hurdle 2 and access Objective-C in swift.

1) Remember Xcode Created a bridging Header for you when you have added a new swift file. Just open that bridging file. The filename should be like the following start from your application name.

ApplicationName-Bridging-Header.h

2) just import the Objective-C class header which you want to access in swift that's it. You are done.
Now you can use the method or members of the class in swift.


Hurray !!! Now you can use both the language in a single application.


One More Thing! Before using both the language in single application let's look some of the challenges you might face? 

Objective-c does not support some Swift Types. Yes like swift struct, enum, tuples and generics are not supported by objective-c; so it is not accessible from Objective-c. If you are facing any challenge that a swift instance method is not visible in objective-c, it might be because method parameter or return type is anyone from the above swift types.

An objective-c class cannot inherit from swift. Yes, a swift class cannot be a base class of objective-c. There could be multiple reasons for it that Apple does not provide this facility. My reasoning is because swift types like struct, enum does not support in Objective-c and if any member variable of swift class is of type swift struct then inheritance cannot be done.

Passed argument in Swift from Objective-C is default Force unwrap. Swift introduced Optional. Each variable declaration in swift must require an optional status. So, when you pass an argument in swift from objective-c, it is followed by a ! (Force unwrap) symbol i.e it can lead to crash or bugs in your application. To avoid the situation, there are two keywords introduced in objective-c which tells the status of the variable:
  • nonnull - Variable cannot be null so in swift it is not optional. 
  • nullable - Variable can be null so in swift, it is the optional type and while you are using that variable in swift, you need to take care of all the check to avoid a crash.
@property (nonatomic, strong, nonnull) NSMutableString *name;
@property (nonatomic, strong, nullable) NSMutableString *address;

In addition to the above, there is a macro which can be used to tell the swift file that all the variables are not optional.

NS_ASSUME_NONNULL_BEGIN

Variable defined between these two macros will be not optional type in swift. You can even define the complete objective-c interface between this two macro and then entire class members are required one.

NS_ASSUME_NONNULL_END

C Macro function cannot be used in the swift file. Since the macro is preprocessed and it is written in C or Objective-C language hence cannot be used in the swift file.


#define SCREEN_WIDTH    [[UIScreen mainScreen] bounds].size.width

The macro function like above will not be visible in the swift file.

One major challenge you can face when you are using both the language in a single project that mistakenly writes a swift code in the objective-c file or vice versa. :)

Thank you for reading the article.

Comments

Popular posts from this blog

Moving from Objective-C To Swift!!!

Swift is a new programming language introduced by apple in WWDC-2014. It is one of the fastest adapted programming language. When apple launch the language I have some question in my mind: 1) What is the need of new programming language? 2) What is wrong with the old one (Objective-c) ? 3) Objective-C will be obsolete? When i reached office next day and discussed about the new language. They are very happy as they found syntax very similar to other language. Now they can easily relate syntax and concept of swift with the other modern languages and quickly learn iOS development. Apple introduced the new language with following tagline 1) Safe 2) Modern 3) Powerful Let have look on the feature of swift: Variable & Properties in Swift: In Objective-C properties and ivar are two different entity. You need to declare a property seperately to access ivar from outside of class. //ViewController.h @interface ViewController : UIViewController { N...