Optimized code version of Jean Le Moignan
static func subclasses<T>(of theClass: T) -> [T] { var count: UInt32 = 0, result: [T] = [] let allClasses = objc_copyClassList(&count)! let classPtr = address(of: theClass) for n in 0 ..< count { let someClass: AnyClass = allClasses[Int(n)] guard let someSuperClass = class_getSuperclass(someClass), address(of: someSuperClass) == classPtr else { continue } result.append(someClass as! T) } return result }
public func address(of object: Any?) -> UnsafeMutableRawPointer{ return Unmanaged.passUnretained(object as AnyObject).toOpaque() }
For each Type, there is only one instance of a metaclass at run time, so pointers to them are unique. For some reason, the === operator is not allowed for AnyClass, but we can directly compare pointers
performance test:
let start = CFAbsoluteTimeGetCurrent() let found = RuntimeUtils.subclasses(of:UIViewController.self) let diff = CFAbsoluteTimeGetCurrent() - start print("Took \(diff) seconds, \(found.count) found")
output:
String (description: theClass): Took 1.0465459823608398 seconds, 174 found
address (from: theClass): Took 0.2642860412597656 seconds, 174 found
source share