Last active
November 13, 2023 23:21
-
-
Save macabeus/eea343bb9119b96eed3393e41dcda0c9 to your computer and use it in GitHub Desktop.
List all classes that subscribe a protocol
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
// 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