2013-10-10 13 views
6

Tôi muốn có được tất cả các lớp học có nguồn gốc (NSString, NSNumber, int, float, NSSet, NSDictionary) mà tôi đã nạp vào dự án iOS của tôi ..Nhận Danh sách tất cả các lớp học có nguồn gốc

tức là, nếu tôi đã tạo một lớp tùy chỉnh có tên là "TestClass" Tôi không muốn nó được liệt kê ...

Tôi đã có mã nhưng nó trả về tên của tất cả các lớp được nạp bất kỳ cách nào tôi có thể sửa đổi mã để giới hạn danh sách thành chỉ lớp Gốc ?

#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 không phải là lớp học. –

+0

@MartinR nhưng điều đó cũng sẽ được đưa vào danh sách trong trường hợp trên !! – Raon

+0

Nếu tôi chạy mã của bạn, tôi nhận được * chỉ * các lớp được xác định trong ứng dụng (AppDelegate, ViewController). Bạn có muốn tất cả các lớp được định nghĩa trong bất kỳ khuôn khổ nào (Foundation, CoreFoundation, UIKit, WebKit, QuartzCore, ...) hay ý bạn là gì bởi "lớp gốc"? –

Trả lời

6

Bạn sẽ nhận được tất cả lớp nạp với

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); 
} 

(Mã số từ objc_getClassList tài liệu.)

Để hạn chế danh sách, bạn có thể kiểm tra mà từ đó các lớp đã được tải, ví dụ

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

cho tất cả các lớp không được tải từ ứng dụng của bạn.

+0

Stackoverflow Nói để tránh cảm ơn ... nhưng tôi phải nói cảm ơn :) – Raon

+0

là có cách nào để lọc ra các lớp học tư nhân và công cộng trong danh sách mà tôi nhận được ở đây? –

+0

Hey Martin, tôi đã thử một giải pháp Swift thuần túy cho câu trả lời của bạn [ở đây] (http://stackoverflow.com/a/36181261/2415822). Bạn có nhớ nhìn và đưa cho tôi một số phản hồi? Cảm ơn! – JAL

3

Dưới đây là một giải pháp Swift tinh khiết với 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)") 
     } 
    } 
} 

giải pháp gốc với 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)") 
     } 
    } 
} 

Lưu ý rằng do cách Swift xử lý con trỏ yếu (protip: nó không), các lớp học của bạn sẽ bị quá tải với mã này. Tôi đã mở SR-1068 về cầu nối __weak__unsafe_unretained con trỏ tới Swift. __weak con trỏ được bắc cầu là UnsafeMutablePointer trong khi __unsafe_unretained con trỏ được bắc cầu là AutoreleasingUnsafeMutablePointer, gây ra quá tải.

May mắn thay, Classes don't do anything on release, vì vậy mã này tương đối an toàn, ít nhất là bây giờ.

+0

Nó phải là '0 ..

+0

@MartinR Tôi đã thay đổi vòng lặp cho nhận xét của bạn. Tôi không thể gọi 'dealloc' trên con trỏ bởi vì tôi đang sử dụng một' AutoreleasingUnsafeMutablePointer' thay vì một 'UnsafeMutablePointer', do đó bộ nhớ nên được deallocated tự động phải không? – JAL

+0

Tôi không nghĩ vậy. Hãy xem mã liên kết đến. –

Các vấn đề liên quan