Created
March 16, 2021 15:30
-
-
Save onevcat/c4fd151c72f9c013136cdb47415b64bf to your computer and use it in GitHub Desktop.
Runtime
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol P: AnyObject { } | |
class A: P {} | |
Runtime.classes(conformTo: P.Type.self) // [MyApp.A] | |
class Runtime { | |
public static func allClasses() -> [AnyClass] { | |
let numberOfClasses = Int(objc_getClassList(nil, 0)) | |
if numberOfClasses > 0 { | |
let classesPtr = UnsafeMutablePointer<AnyClass>.allocate(capacity: numberOfClasses) | |
let autoreleasingClasses = AutoreleasingUnsafeMutablePointer<AnyClass>(classesPtr) | |
let count = objc_getClassList(autoreleasingClasses, Int32(numberOfClasses)) | |
assert(numberOfClasses == count) | |
defer { classesPtr.deallocate() } | |
let classes = (0 ..< numberOfClasses).map { classesPtr[$0] } | |
return classes | |
} | |
return [] | |
} | |
public static func subclasses(of `class`: AnyClass) -> [AnyClass] { | |
return self.allClasses().filter { | |
var ancestor: AnyClass? = $0 | |
while let type = ancestor { | |
if ObjectIdentifier(type) == ObjectIdentifier(`class`) { return true } | |
ancestor = class_getSuperclass(type) | |
} | |
return false | |
} | |
} | |
public static func classes(conformToProtocol `protocol`: Protocol) -> [AnyClass] { | |
let classes = self.allClasses().filter { aClass in | |
var subject: AnyClass? = aClass | |
while let aClass = subject { | |
if class_conformsToProtocol(aClass, `protocol`) { print(String(describing: aClass)); return true } | |
subject = class_getSuperclass(aClass) | |
} | |
return false | |
} | |
return classes | |
} | |
public static func classes<T>(conformTo: T.Type) -> [AnyClass] { | |
return self.allClasses().filter { $0 is T } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment