导语
本文主要简单描述了在 OC & Swift 混编工程中,两者是如何相互调用的,顺便实现在 Swift 中获取类的属性。
环境
macOS Sierra 10.12.4
Xcode 8.3.1
Swift 3.0
流程
Swift
调用 OC
在 OC 编程语言编写的源工程中,当创建 Swift 文件时,根据提示创建好桥接文件。在桥接文件中有如下注释
Use this file to import your target’s public headers that you would like to expose to Swift.
通过在该文件引入头文件可以顺利实现在 Swift 中调用 OC 方法。
OC
调用 Swift
查看 Build Settings ,其中有一项 Swift Compiler - General 如下图所示
其中 Objective-C Bridging Header 字段即为桥接文件。下面的 Objective-C Generated interface Header Name 字段就是 OC 中调用 Swift 类时需要引入的头文件。该字段的值的规则为 工程名-Swift.h
1 | // 引入头文件 |
按住 ⌘ 进入 TouchIDViewController
1 | @import UIKit; |
在运行时工程的 objc-runtime-new.h 头文件中
1 | struct objc_class : objc_object { |
可以了解到 Swift 编写的类也就会被运行时处理。
Swift
的类的名称
比如当前工程的 _TtC13Daily_modules21TouchIDViewController
如何来的。
前缀 _TtC
工程名的长度: 13
工程名: Daily_modles
类名的长度: 21
类名: TouchIDViewController
1 | extension NSObject { |
上面是一个获取 Swift 类的 extension
Swift
版获取类的属性
1 | public class func getPropertiesInfo(cls:AnyClass?, recursive:Bool) -> Any! { |
只能获取 public / open 访问范围的属性 + OC 原有的属性
总结
在 Swift 的注释中如下的一段话
/// Accessing Objective-C Methods and Properties
/// ============================================
///
/// When you useAnyObject
as a concrete type, you have at your disposal
/// every@objc
method and property—that is, methods and properties
/// imported from Objective-C or marked with the@objc
attribute. Because
/// Swift can’t guarantee at compile time that these methods and properties
/// are actually available on anAnyObject
instance’s underlying type, these
///@objc
symbols are available as implicitly unwrapped optional methods and
/// properties, respectively.
这一点和参考链接中提到的表达是有关的
纯Swift类的函数调用已经不再是Objective-c的运行时发消息,而是类似C++的vtable,在编译时就确定了调用哪个函数,所以没法通过runtime获取方法、属性。
TestSwiftVC继承自UIViewController,基类NSObject,而Swift为了兼容Objective-C,凡是继承自NSObject的类都会保留其动态性,所以我们能通过runtime拿到他的方法。
Swift 不能通过运行时获取对应类的属性和方法,但是如果是继承自 NSObject( imported from Objective-C ) 或被标记了 @objc 则可以被获取,能被获取到的属性也是有所限制的。