Swift (compatibility with Objective-C)

Time:2022-5-6

Although the original intention of swift language is to get rid of the heavy historical burden and constraints of Objective-C, it is undeniable that after more than 20 years of baptism, cocoa framework has long been branded with the indelible mark of Objective-C. Countless third-party libraries are written in Objective-C. no one can underestimate these accumulations. Therefore, in the initial version, swift had to consider compatibility with Objective-C.

Apple’s approach is to allow us to use both swift and Objective-C for development in the same project. In fact, Objective-C files and swift files in a project are in two different worlds. In order to connect them with each other, we need to add some bridges.

First, add {product module name} – bridging header H file and fill in the name of the header file you want to use, so we can easily use Objective-C code in swift. In order to simplify this setting, Xcode will even pop up a box to ask whether to automatically create this file when importing the Objective-C file for the first time in swift project. It can be said to be very convenient.

But if you want to use Swift’s type in Objective-C, things are more complicated. If it comes from an external framework, the framework and Objective-C project are certainly not in the same target. We need to import the external swift module. This is actually the same as the original framework using Objective-C. for a project, there is no big difference between whether the external framework is written by swift or Objective-C. By using the new technology introduced in 2013@importTo import a module:

@import MySwiftKit; 

After that, you can use the framework written by swift normally.

If you want to use the source file of swift in the same project in Objective-C, you can directly import the automatically generated header file {product module name} – swift H to complete. For example, if the target of the project is called myapp, we need to write it in the Objective-C file

#import "MyApp-Swift.h"

But this is just the beginning of the story. Objective-C and swift use two completely different mechanisms at the bottom. The Objective-C object in cocoa is based on the runtime. It follows KVC (key value coding, which stores object information in a dictionary like way) and dynamic dispatch (dynamic dispatch, which determines the specific implementation of the actual call when running the call). In order to pursue performance, swift will not decide these at runtime if there are no special needs. In other words, the members or methods of swift type have been determined at compile time, and the runtime does not need to go through a search, but can be used directly.

Obviously, the problem is that if we want to use Objective-C code or features to call pure swift types, we will fail because we can’t find the required runtime information. The solution is also very simple. In swift type files, we can add the @ objc modifier in front of the declaration that needs to be exposed to any place used by Objective-C (including classes, attributes and methods). Note that this step only needs to be performed on those types that do not inherit from nsobject. If the class you write in swift inherits from nsobject, swift will automatically add @ objc to all non private classes and members by default. That is to say, for a subclass of nsobject, you only need to import the corresponding header file to use this class in Objective-C.

@Another function of objc modifier is to redeclare the name of method or variable for Objective-C side. Although most of the time, the automatically converted method names are easy enough to use (for example, methods like init (Name: String) in swift will be converted to – initwithname: (nsstring *) name), sometimes we still expect Objective-C to use method names or class names that are different from those in swift, such as a class in swift:

Class my class{  
    Func say hello (Name: String){  
        Println ("Hello, \ (name)")  
    }  
}  
 
My class () Say hello ("Xiao Ming")

Objective-C cannot be called in Chinese, so we must use @ objc to convert it to ASCII in order to access it in Objective-C:

@objc(MyClass)  
Class my class{  
    @objc(greeting:)  
    Func say hello (Name: String){  
        Println ("Hello, \ (name)")  
    }  
}

We can call [[MyClass new] greeting: @ “Xiaoming”] in Objective-C (although it’s not fun at all). In addition, as mentioned above and mentioned in the selector section, even if it is a subclass of nsobject, swift will not automatically add @ objc to the method or member marked private. If we need to use the dynamic features of these contents, we need to manually add @ objc decoration to them.

Adding the @ objc modifier does not mean that this method or property will become a dynamic dispatch. Swift may still optimize it into a static call. If you need the same runtime features as dynamic call in Objective-C, the modifier you need to use is dynamic. In general, it should not be used in app development, but we need to use the dynamic modifier when performing some “black magic” such as dynamic replacement methods or when the runtime decides to implement them. In the following KVO section, we will also mention an example of using dynamic.

This article is excerpted from Wang Wei