2013-10-10 17 views
6

voglio ottenere tutte le classi native (NSString, NSNumber, int, float, NSSet, NSDictionary) che ho caricato nel mio progetto iOS ..Ottenere Elenco di tutte le classi native

cioè, se ho creato una classe personalizzata denominata "TestClass" Non voglio elencarla ...

Ho già ottenuto un codice ma restituisce i nomi di tutte le classi caricate in qualsiasi modo posso modificare il codice per limitare l'elenco solo alle classi native ?

#import <objc/runtime.h> 
#import <dlfcn.h> 
#import <mach-o/ldsyms.h> 


unsigned int count; 
const char **classes; 
Dl_info info; 

dladdr(&_mh_execute_header, &info); 
classes = objc_copyClassNamesForImage(info.dli_fname, &count); 

for (int i = 0; i < count; i++) { 
    NSLog(@"Class name: %s", classes[i]); 
    Class class = NSClassFromString ([NSString stringWithCString:classes[i] encoding:NSUTF8StringEncoding]); 
    // Do something with class 

} 
+0

int, float non sono classi. –

+0

@MartinR ma che entrerà anche nella lista nel caso di cui sopra !! – Raon

+0

Se eseguo il codice, ottengo * solo * le classi definite nell'app (AppDelegate, ViewController). Vuoi tutte le classi definite in qualsiasi framework (Foundation, CoreFoundation, UIKit, WebKit, QuartzCore, ...) o cosa intendi per "classi native"? –

risposta

6

Si otterrebbe tutti classi caricate con

int numClasses; 
Class * classes = NULL; 

classes = NULL; 
numClasses = objc_getClassList(NULL, 0); 

if (numClasses > 0) 
{ 
    classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses); 
    numClasses = objc_getClassList(classes, numClasses); 
    for (int i = 0; i < numClasses; i++) { 
     Class c = classes[i]; 
     NSLog(@"%s", class_getName(c)); 
    } 
    free(classes); 
} 

(codice da objc_getClassList documentazione.)

Per limitare l'elenco, è possibile controllare il fascio da cui la classe è stato caricato, ad es

Class c = classes[i]; 
NSBundle *b = [NSBundle bundleForClass:c]; 
if (b != [NSBundle mainBundle]) 
    ... 

per tutte le classi non caricate dall'applicazione.

+0

Stackoverflow Dire di evitare grazie ... ma devo dire grazie :) – Raon

+0

c'è un modo per filtrare le classi pubbliche e private nell'elenco che ho qui? –

+0

Hey Martin, ho tentato una soluzione rapida pura della tua risposta [qui] (http://stackoverflow.com/a/36181261/2415822). Ti dispiacerebbe dare un'occhiata e darmi un feedback? Grazie! – JAL

3

Ecco una soluzione Swift pura con Swift 3:

var numClasses: Int32 = 0 
var allClasses: AutoreleasingUnsafeMutablePointer<AnyClass?>? = nil 
defer { 
    allClasses = nil 
} 

numClasses = objc_getClassList(nil, 0) 

if numClasses > 0 { 
    var ptr = UnsafeMutablePointer<AnyClass?>.allocate(capacity: Int(numClasses)) 
    defer { 
     ptr.deinitialize() 
     ptr.deallocate(capacity: Int(numClasses)) 
    } 
    allClasses = AutoreleasingUnsafeMutablePointer<AnyClass?>(ptr) 
    numClasses = objc_getClassList(allClasses, numClasses) 

    for i in 0 ..< numClasses { 
     if let currentClass: AnyClass = allClasses?[Int(i)] { 
      print("\(currentClass)") 
     } 
    } 
} 

soluzione originale con Swift 2.2/Xcode 7.3:

var numClasses: Int32 = 0 
var allClasses: AutoreleasingUnsafeMutablePointer<AnyClass?> = nil 
defer { 
    allClasses = nil 
} 

numClasses = objc_getClassList(nil, 0) 

if numClasses > 0 { 
    var ptr = UnsafeMutablePointer<AnyClass>.alloc(Int(numClasses)) 
    defer { 
     ptr.destroy() 
     ptr.dealloc(Int(numClasses)) 
     ptr = nil 
    } 
    allClasses = AutoreleasingUnsafeMutablePointer<AnyClass?>.init(ptr) 
    numClasses = objc_getClassList(allClasses, numClasses) 

    for i in 0 ..< numClasses { 
     if let currentClass: AnyClass = allClasses[Int(i)] { 
      print("\(currentClass)") 
     } 
    } 
} 

Nota che a causa del modo in cui Swift gestisce i puntatori deboli (PROTIP: si non lo è), le tue classi saranno sopraffatte da questo codice. Ho aperto SR-1068 a colmare __weak e __unsafe_unretained puntatori a Swift. __weak puntatori sono collegati a ponte come UnsafeMutablePointer mentre __unsafe_unretained puntatori sono collegati a ponte come AutoreleasingUnsafeMutablePointer, che provoca l'overrelase.

Fortunatamente, Classes don't do anything on release, quindi questo codice è relativamente sicuro, almeno per ora.

+0

Dovrebbe essere '0 ..

+0

@MartinR Ho cambiato il ciclo for per il tuo commento. Non posso chiamare 'dealloc' sul puntatore perché sto utilizzando un' AutoreleasingUnsafeMutablePointer' piuttosto che un 'UnsafeMutablePointer', quindi la memoria dovrebbe essere deallocato automaticamente giusto? – JAL

+0

Non penso. Dai un'occhiata al codice linkato. –

Problemi correlati