title: swift: get method list, argument names & types
body: <p>I’m trying to figure it out how to work with Objective-C Runtime. </p>
  
  <p>There’s a class that has several methods defined through @objc extension. I want to get list of these methods with argument names and types. Something similar I get using <code>print(#function, type(of: methodName))</code> - but this is in case if I call it inside this method, whereas I need to get all this stuff from outside. </p>
  
  <p>I use <code>class_copyMethodList</code> and <code>method_getName</code>, but I get something like</p>
  
  <blockquote>
    <p>method3WithArg1:arg2:</p>
  </blockquote>
  
  <p>whereas #function and type(of: method) gives</p>
  
  <blockquote>
    <p>method3(arg1:arg2:) (Int, Double) -> ()</p>
  </blockquote>
  
  <p><code>method_getNumberOfArguments</code> gives 2 more arguments, <code>method_getArgumentType</code> gives types like q, d, @. Last two I understand, but why q instead of f? (<a href="https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html" rel="nofollow noreferrer">https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html</a>). 
  It would be better to get something familiar like method3(arg1: Int, arg2: Double). Question: do I have to do this manually or there are some other ways?</p>
  
  <p>Further, I want to choose one method from the list, get parameters that it needs, assign that to chosenMethod variable, so that I could call it later. How do I make a closure from Selector? And do I need selectors at all?</p>
  
  <p>Generally, there are some funcs in the class, some will be added later. User is asked to choose method from available, fill the arguments and simply call it. </p>
  
  <pre><code>class MyClass {
  
      var chosenMethod: ((MyStruct) -&gt; ())?
  
      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() -&gt; [Selector] {
  
      var methodCount: UInt32 = 0
      guard let methodList = class_copyMethodList(MyStruct.self, &amp;methodCount) else { return [] }
  
      var selectors = [Selector]()
      let maxChars = 256
      let ctype = UnsafeMutablePointer&lt;Int8&gt;.allocate(capacity: maxChars)
      for i in 0 ..&lt; 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 ..&lt; 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()
  </code></pre>