今天隔壁老王突然问起我,Swift里面的@objc是个神马玩意儿?于是就有了今天的这个tip。那么话说回来,既然说到@objc,就不得不扯一扯Swift和Objective-C之间不得不说的一些事啦^_^
Objective-c and Swift Hybrid development
The original purpose of Swift language is to hope to get rid of the heavy historical burden and restraint of objective-c, but it is undeniable that after more than 20 years of baptism, the COCOA framework has long been branded an indelible mark of objective-c. Countless third-party libraries are written in objective-c, and these accumulations can be underestimated by no one. Therefore, in the initial version, Swift had to consider compatibility with objective-c.
Apple's approach is to allow us to use Swift and objective-c for development in the same project. In fact, the objective-c files and Swift files in a project are in two different worlds, and in order for them to be interconnected, we need to add some bridges.
Of course this bridge file, in the new Xcode version, is automatically prompted whether it needs to be generated, and to help you automatically generated, so do not need to care about this issue.
@objc Use scenario One:
Objective-C 和 Swift 在底层使用的是两套完全不同的机制,Cocoa 中的 Objective-C 对象是基于运行时的,它从骨子里遵循了 KVC (Key-Value Coding,通过类似字典的方式存储对象信息) 以及动态派发 (Dynamic Dispatch,在运行调用时再决定实际调用的具体实现)。而 Swift 为了追求性能,如果没有特殊需要的话,是不会在运行时再来决定这些的。也就是说,Swift 类型的成员或者方法在编译时就已经决定,而运行时便不再需要经过一次查找,而可以直接使用。
Obviously, this is one of the use scenarios of @objc,如果我们要使用 Objective-C 的代码或者特性来调用纯 Swift 的类型时候,我们会因为找不到所需要的这些运行时信息,而导致失败。
Attention:
This step only needs to be done for those types that are not inherited from NSObject, if you write the class with Swift 继承自 NSObject
Swift 会默认自动为所有的非 private 的类和成员加上 @objc
. This means that for a nsobject subclass, you just need to import the appropriate header file to use this class in Objective-c.
Use Scenario two for @objc:
虽然绝大部分时候自动转换的方法名已经足够好用 (比如会将 Swift 中类似 init(name: String) 的方法转换成 -initWithName:(NSString *)name 这样),但是有时候我们还是期望 Objective-C 里使用和 Swift 中不一样的方法名或者类的名字,比如 Swift 里这样的一个类:class Person{ func Hello(name: String) { println("Hello,\(name)") }}Person().Hello("小明")
Can be modified by @objc
@objc(MyClass)class Person{ @objc(greeting:) func Hello(name: String) { println("Hello,\(name)") }}
Then we can do the call in Objective-c:[[MyClass new] greeting:@"小明"]
Finally make a note:
Description
Adding a @objc modifier does not mean that the method or property will become dynamically distributed, and Swift may still optimize it for static invocation. If you need the same runtime attributes as the dynamic call in Objective-c, the modifier you need to use is the dynamic.
Swift Learning tip of the Day (7) @objc