Skip to content

Instantly share code, notes, and snippets.

@macabeus
Last active November 13, 2023 23:21
Show Gist options
  • Save macabeus/eea343bb9119b96eed3393e41dcda0c9 to your computer and use it in GitHub Desktop.
Save macabeus/eea343bb9119b96eed3393e41dcda0c9 to your computer and use it in GitHub Desktop.
List all classes that subscribe a protocol
// Many thanks to Code Different: http://stackoverflow.com/a/42749141/3440266
import Foundation
struct ClassInfo : CustomStringConvertible, Equatable {
let classObject: AnyClass
let classNameFull: String
let className: String
init?(_ classObject: AnyClass?) {
guard classObject != nil else { return nil }
self.classObject = classObject!
let cName = class_getName(classObject)!
self.classNameFull = String(cString: cName)
self.className = self.classNameFull.components(separatedBy: ".").last!
}
var superclassInfo: ClassInfo? {
let superclassObject: AnyClass? = class_getSuperclass(self.classObject)
return ClassInfo(superclassObject)
}
var description: String {
return self.classNameFull
}
static func ==(lhs: ClassInfo, rhs: ClassInfo) -> Bool {
return lhs.classNameFull == rhs.classNameFull
}
}
////
// List classes that are subclasses
func subclasses(of classMother: AnyClass) -> [ClassInfo] {
let motherClassInfo = ClassInfo(classMother.self)!
var subclassesList = [ClassInfo]()
var count = UInt32(0)
let classList = objc_copyClassList(&count)!
for i in 0..<Int(count) {
if let classInfo = ClassInfo(classList[i]),
let superclassInfo = classInfo.superclassInfo,
superclassInfo == motherClassInfo
{
subclassesList.append(classInfo)
}
}
return subclassesList
}
// Example
class Mother { }
class Brother: Mother { }
class Sister: Mother { }
class Cousin { }
let listSubclasses = subclasses(of: Mother.self)
print(listSubclasses)
////
// List classes that subscribers a protocol
func subscribers<T>(of: T.Type) -> [ClassInfo] {
var subscribersList = [ClassInfo]()
var count = UInt32(0)
let classList = objc_copyClassList(&count)!
for i in 0..<Int(count) {
if let classInfo = ClassInfo(classList[i]) {
// skip native Swift and Foundation classes, to do not crash
if classInfo.classNameFull.components(separatedBy: ".").count == 1 {
continue
}
//
if classInfo.classObject is T {
subscribersList.append(classInfo)
}
}
}
return subscribersList
}
// Example
protocol Proto { }
protocol Proto2 { }
class Foo: Proto { }
class Bar: Proto, Proto2 { }
class Baz: Proto2 { }
class Qux { }
let listProto = subscribers(of: Proto.Type.self )
print(listProto)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment