2017-07-13 1 views
1

Ich versuche, eine Liste der Klassen zu erhalten, die ein bestimmtes Protokoll Migration: Preparation angenommen haben, und dann diese Klassen an ein Array anzuhängen. Hier ist die Funktion in Frage:Leere Konstante beim Versuch, eine Liste der Klassen zu erhalten, die ein Protokoll angenommen haben

struct Migrations { 

static func getMigrations() -> [Preparation.Type] { 
    var migrationsList = [Preparation.Type]() 
    var count = UInt32(0) 
    let classList = objc_copyClassList(&count)! 


    for i in 0..<Int(count) { 
     let classInfo = ClassInfo(classList[i])! 
     if let cls = classInfo.classObject as? Migration.Type { 
      migrationsList.append(cls) 
      print(cls.description) 
     } 
    } 
    return migrationsList 
} 
} 

Im Prinzip alles, was sollte funktionieren, aber beim Debuggen Ich nehme zur Kenntnis, dass der Class Variable für jede Klasse in der Iteration bezieht, aber bei der Zuordnung und in der if let as Linie Gießen, die Konstante cls ist immer leer - weder ein Wert/Klasse noch nil, nur komplett leer.

Irgendeine Idee, was ich mit diesem Code falsch verstanden habe?

Ich bin auch offen für Vorschläge für einen besseren Weg, um eine Liste aller Klassen zu erhalten, die ein bestimmtes Protokoll angenommen haben ...

EDIT: ich den Code zur Verfügung zu stellen vergessen für ClassInfo

import Foundation 

struct ClassInfo: CustomStringConvertible, Equatable { 
    let classObject: AnyClass 
    let className: String 

    init?(_ classObject: AnyClass?) { 
     guard classObject != nil else { return nil } 

     self.classObject = classObject! 

     let cName = class_getName(classObject)! 
     self.className = String(cString: cName) 
    } 

    var superclassInfo: ClassInfo? { 
     let superclassObject: AnyClass? = class_getSuperclass(self.classObject) 
     return ClassInfo(superclassObject) 
    } 

    var description: String { 
     return self.className 
    } 

    static func ==(lhs: ClassInfo, rhs: ClassInfo) -> Bool { 
     return lhs.className == rhs.className 
    } 
} 
+0

Also macht der Code es zu 'migrationsList.append (cls)'? –

+0

So ist es schwer für mich, genau zu sagen, was vor sich geht, da ich mit 'ClassInfo' nicht sehen kann, aber ich kann Ihnen aus Erfahrung sagen, dass Sie nicht in der Lage sein werden, wenn Sie eine Variable mit einem Metatyp haben sieh es in lldb. Versuchen Sie es direkt zu drucken, oder drücken Sie 'type (of: thing)' –

+0

Ich habe den 'ClassInfo' Code hinzugefügt, sorry! Was deine erste Frage @AllenHumphreys anbelangt, so kommt sie leider nie so weit. Ich habe sichergestellt, dass es in meinem Code mindestens eine Klasse gibt, die das 'Migration'-Protokoll übernommen hat, also sollte es mindestens einen Treffer geben ... – cyehia

Antwort

0

Ich kann nicht erklären, warum cls immer leer ist, wie ich in meinem Kommentar sagte, es ist etwas, in das ich jedes Mal hineinstoße, wenn ich mit Metatypen zu tun habe. Damit der Code wie vorgesehen funktioniert, habe ich this q&a gefunden und mit Swift 3 aktualisiert, um diesen Code zu erhalten, der Ihre Situation abdecken sollte. Es ist wichtig zu betonen, dass dies nur funktioniert, wenn Sie Swift der Objective-C-Laufzeit korrekt aussetzen.

Lassen Sie diesen Code überall hin und rufen Sie print(Migrations.getMigrations()) von einem bequemen Einstiegspunkt.

struct Migrations { 

    static func getMigrations() -> [Preparation.Type] { 

     return getClassesImplementingProtocol(p: Preparation.self) as! [Preparation.Type] 
    } 

    static func getClassesImplementingProtocol(p: Protocol) -> [AnyClass] { 
     let classes = objc_getClassList() 
     var ret = [AnyClass]() 

     for cls in classes { 
      if class_conformsToProtocol(cls, p) { 
       ret.append(cls) 
      } 
     } 

     return ret 
    } 

    static func objc_getClassList() -> [AnyClass] { 
     let expectedClassCount = ObjectiveC.objc_getClassList(nil, 0) 
     let allClasses = UnsafeMutablePointer<AnyClass?>.allocate(capacity: Int(expectedClassCount)) 
     let autoreleasingAllClasses = AutoreleasingUnsafeMutablePointer<AnyClass?>(allClasses) 
     let actualClassCount:Int32 = ObjectiveC.objc_getClassList(autoreleasingAllClasses, expectedClassCount) 

     var classes = [AnyClass]() 
     for i in 0 ..< actualClassCount { 
      if let currentClass: AnyClass = allClasses[Int(i)] { 
       classes.append(currentClass) 
      } 
     } 

     allClasses.deallocate(capacity: Int(expectedClassCount)) 

     return classes 
    } 
} 

class Migration: Preparation { 

} 

@objc 
protocol Preparation { 

} 
Verwandte Themen