我正在试图弄清楚如何使用Objective-C Runtime。
有一个类有几个通过@objc扩展定义的方法。我想用参数名称和类型获取这些方法的列表。我使用print(#function, type(of: methodName))
得到类似的东西 - 但如果我在这个方法中调用它,以防万一我需要从外部获取所有这些东西。
我使用class_copyMethodList
和method_getName
,但我得到类似
method3WithArg1:ARG2:
而#function和type(of:method)给出了
method3(arg1:arg2:)(Int,Double) - > ()
method_getNumberOfArguments
再给出2个参数,method_getArgumentType
给出q,d,@等类型。最后两个我理解,但为什么q而不是f? (https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html)。
得到像method3(arg1:Int,arg2:Double)这样熟悉的东西会更好。问题:我是否必须手动执行此操作或有其他方法?
此外,我想从列表中选择一个方法,获取所需的参数,将其分配给selectedMethod变量,以便稍后调用它。如何从Selector进行闭包?我需要选择器吗?
通常,类中有一些函数,有些将在以后添加。要求用户从可用方法中选择方法,填写参数并简单地调用它。
class MyClass {
var chosenMethod: ((MyStruct) -> ())?
func execute() {
chosenMethod?(self)
}
}
@objc extension MyClass {
func method0() {
print(#function, type(of: method0), "\n")
}
func method1(_ arg1: String) {
print(#function, type(of: method1), "\n")
}
func method2(_ arg1: Int, _ arg2: Double) {
print(#function, type(of: method2), "\n")
}
func method3(arg1: Int, arg2: Double) {
print(#function, type(of: method3), "\n")
}
}
//extension MyStruct {
// @objc(arg1:arg2:) func method4(arg1: Int, arg2: Double) {
// print(#function, type(of: method4), "\n")
// }
//}
func getMethods() -> [Selector] {
var methodCount: UInt32 = 0
guard let methodList = class_copyMethodList(MyStruct.self, &methodCount) else { return [] }
var selectors = [Selector]()
let maxChars = 256
let ctype = UnsafeMutablePointer<Int8>.allocate(capacity: maxChars)
for i in 0 ..< Int(methodCount) {
let method = methodList[i]
let selector: Selector = method_getName(method)
selectors.append(selector)
print("name: \(String(cString: sel_getName(selector)))")
let numberOfArguments = method_getNumberOfArguments(method) - 2
print("numberOfArguments: \(numberOfArguments)")
for j in 2 ..< Int(numberOfArguments) + 2 {
method_getArgumentType(method, UInt32(j), ctype, maxChars)
print("argumentType: \(String(cString: ctype))")
}
print()
}
free(methodList)
return selectors
}
let myStruct = MyStruct()
myStruct.method0()
myStruct.method1("check")
myStruct.method2(0, 1.0)
myStruct.method3(arg1: 0, arg2: 1.0)
print("---\n")
let methods = getMethods()
myStruct.chosenMethod = { $0.method2(0, 1.0) }
//myStruct.chosenMethod = { $0.methods[1](0, 1.0) }
myStruct.execute()