如何从协议方法描述列表中解密"objc_method_description"?
How to decipher "objc_method_description" from protocol method description list?
我有一些 Swift 3 代码来解码 iOS Objective-C 协议(它有一个 Swift 对应协议)。在断定 Swift 3 反射还没有开发到足以完成我需要的东西之后,我偶然发现了 objc 运行时方法 protocol_copyMethodDescriptionList()
,它 returns 以下 C 结构的数组:
struct objc_method_description
SEL name;
char *types;
};
代码获取协议选择器名称列表,但不确定 type
字段中返回的是什么。我对如何正确解码 objc_method_description.type
值感到困惑。
我在 type
字段中得到的是一种神秘格式,例如,"B48@0:8@16{_NSRange=QQ}24@40"
起初我认为这是我如何转换 C 字符串的问题,但是经过一些研究,我怀疑它实际上 是 参数的编码,类似于 Java 的 JVM 传递方法签名的方式。但是我仍然没有解码它的参考。
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet weak var noteView : UITextView!
func decodeProto() {
var methodCount : UInt32 = 1
if let methodList = protocol_copyMethodDescriptionList(UITextViewDelegate.self,
false, true, UnsafeMutablePointer<UInt32>(&methodCount)) {
for i in 0..<Int(methodCount) {
let methodDesc = methodList[i];
let name = methodDesc.name
let types = String(validatingUTF8: methodDesc.types)
print("\(name) \(types)")
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
decodeProto()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
XCode 控制台中的输出是:
Optional(textViewDidBeginEditing:
) Optional("v24@0:8@16")
Optional(textViewDidEndEditing:
) Optional("v24@0:8@16")
Optional(textViewShouldBeginEditing:
) Optional("B24@0:8@16")
Optional(textViewShouldEndEditing:
) Optional("B24@0:8@16")
Optional(textView:shouldChangeTextInRange:replacementText:
) Optional("B48@0:8@16{_NSRange=QQ}24@40")
Optional(textView:shouldChangeTextInRange:replacementText:) Optional("B48@0:8@16{_NSRange=QQ}24@40")
.
.
.
objc_method_description.type
字段返回什么?
- 一种方法签名编码方案
- ... 其中包括 过时的堆栈偏移表示法
换句话说,要从 type
字段中获得 可用的 方法签名编码,只需按从左到右的顺序提取字母符号字符丢弃数字。
支持文档:
- Objective-C Method Signature Type Encoding
- Meaning of the numeric elements in signature encoding, explained by an Apple developer
- Playing around with Type Encodings
- class_addmethod (根据@Richard_J_Ross,这是它的根源)
- Objective-C Runtime Programming Guide
- Objective-C Runtime Reference
我有一些 Swift 3 代码来解码 iOS Objective-C 协议(它有一个 Swift 对应协议)。在断定 Swift 3 反射还没有开发到足以完成我需要的东西之后,我偶然发现了 objc 运行时方法 protocol_copyMethodDescriptionList()
,它 returns 以下 C 结构的数组:
struct objc_method_description
SEL name;
char *types;
};
代码获取协议选择器名称列表,但不确定 type
字段中返回的是什么。我对如何正确解码 objc_method_description.type
值感到困惑。
我在 type
字段中得到的是一种神秘格式,例如,"B48@0:8@16{_NSRange=QQ}24@40"
起初我认为这是我如何转换 C 字符串的问题,但是经过一些研究,我怀疑它实际上 是 参数的编码,类似于 Java 的 JVM 传递方法签名的方式。但是我仍然没有解码它的参考。
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet weak var noteView : UITextView!
func decodeProto() {
var methodCount : UInt32 = 1
if let methodList = protocol_copyMethodDescriptionList(UITextViewDelegate.self,
false, true, UnsafeMutablePointer<UInt32>(&methodCount)) {
for i in 0..<Int(methodCount) {
let methodDesc = methodList[i];
let name = methodDesc.name
let types = String(validatingUTF8: methodDesc.types)
print("\(name) \(types)")
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
decodeProto()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
XCode 控制台中的输出是:
Optional(
textViewDidBeginEditing:
) Optional("v24@0:8@16")
Optional(textViewDidEndEditing:
) Optional("v24@0:8@16")
Optional(textViewShouldBeginEditing:
) Optional("B24@0:8@16")
Optional(textViewShouldEndEditing:
) Optional("B24@0:8@16")
Optional(textView:shouldChangeTextInRange:replacementText:
) Optional("B48@0:8@16{_NSRange=QQ}24@40")
Optional(textView:shouldChangeTextInRange:replacementText:) Optional("B48@0:8@16{_NSRange=QQ}24@40")
.
.
.
objc_method_description.type
字段返回什么?
- 一种方法签名编码方案
- ... 其中包括 过时的堆栈偏移表示法
换句话说,要从 type
字段中获得 可用的 方法签名编码,只需按从左到右的顺序提取字母符号字符丢弃数字。
支持文档:
- Objective-C Method Signature Type Encoding
- Meaning of the numeric elements in signature encoding, explained by an Apple developer
- Playing around with Type Encodings
- class_addmethod (根据@Richard_J_Ross,这是它的根源)
- Objective-C Runtime Programming Guide
- Objective-C Runtime Reference