Swift 5 reflection get list of class properties and call them

Viewed 385

I have a class that uses class computed variables that may be accessed from both objc-c and swift. I would like to test all these properties that start with "const".

I have this:

import UIKit

class MyClass: NSObject {
    @objc class var  constMethod1 : UIColor {
    print("Method1")
    return UIColor.red
  }

  @objc class var  constMethod2 : UIColor {
    print("Method2")
    return UIColor.green
  }
}

var methodCount: UInt32 = 0
let methodList = class_copyMethodList(MyClass.self, &methodCount)

for i in 0..<Int(methodCount){
   let unwrapped = methodList?[i]
    // call method only if it starts with "const"
    let crtMethodStr = NSStringFromSelector(method_getName(unwrapped!))
   print(crtMethodStr)
    
    if crtMethodStr.hasPrefix("const") {
        // call it
    }
}

All I get is "init" in the return array? what is the problem? I saw on another thread that just adding "@objc" shoulld fix this. Also how do I access one of these variables from the retuned array?

1 Answers

From the docs:

Describes the instance methods implemented by a class.

constMethod1 and constMethod2 are computed class properties, which translates to class methods in Objective-C. So they won't be returned by class_copyMethodList. But fear not, the docs also say:

To get the class methods of a class, use class_copyMethodList(object_getClass(cls), &count).

So you can do:

let methodList = class_copyMethodList(object_getClass(MyClass.self), &methodCount)

To call it, you can use perform:

if crtMethodStr.hasPrefix("const") {
    let result = MyClass.perform(method_getName(unwrapped!))!.takeUnretainedValue()
    print(result)
}
Related