swift:获取方法列表,参数名称和类型

时间:2018-04-21 13:38:51

标签: swift

我正在试图弄清楚如何使用Objective-C Runtime。

有一个类有几个通过@objc扩展定义的方法。我想用参数名称和类型获取这些方法的列表。我使用print(#function, type(of: methodName))得到类似的东西 - 但如果我在这个方法中调用它,以防万一我需要从外部获取所有这些东西。

我使用class_copyMethodListmethod_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()

0 个答案:

没有答案