2012-02-12 38 views
16

Có cách nào để lặp qua tất cả các thuộc tính trong một đối tượng và nhận được "tên" và "giá trị" của chúng hay không.Mục tiêu- C - Lặp qua tất cả các thuộc tính trong một lớp?

Tôi đang cố viết một danh mục để sắp xếp các đối tượng theo chuỗi, dựa trên tên và giá trị thuộc tính của chúng. Tôi đang cố gắng để ngăn chặn viết phương pháp mã hóa cho mỗi lớp, và thay vì viết một chung chung.

Điều này có khả thi không?

+3

Một ý tưởng đáng ngưỡng mộ, nhưng xuống con đường đó nằm điên rồ. Bạn sẽ phát minh lại bánh xe (Dữ liệu cốt lõi đã cung cấp sự kiên trì dựa trên mô hình xuất sắc) và hệ thống thuộc tính * không * được thiết kế làm cơ sở cho bất kỳ loại độ bền tự động nào. Kết quả cuối cùng sẽ cực kỳ mong manh và sẽ là một nỗi đau hoàn toàn để viết ở nơi đầu tiên, với những thay đổi bất thường của các kiểu dữ liệu C. – bbum

+0

Mặc dù upvote của tôi về "tài sản xin vui lòng" câu trả lời dưới đây ... Đây là khi bạn cần phải đi học Core Data. Nghiêm túc, nó sẽ có giá trị nó. Nó không phải dành cho người mới bắt đầu mà là IMO khi bạn bắt đầu thực hiện các công cụ như hack thời gian chạy objc, đó là lúc để đọc những tài liệu lạ đó và làm cho đầu của bạn làm việc đúng cách. :) – buildsucceeded

+0

@buildsucceeded Tôi biết cách sử dụng dữ liệu cốt lõi. Đó là một giải pháp tuyệt vời khi nói đến một dự án có kích thước trung bình/lớn yêu cầu dữ liệu quan hệ. Nhưng khi nói đến một dự án thực sự nhỏ, nơi mà tất cả những gì tôi cần để sắp xếp một đối tượng duy nhất để giữ trạng thái của ứng dụng, đó là một sự tiêu diệt quá mức để sử dụng dữ liệu lõi. Thêm vào đó, tôi đã sử dụng giải pháp này cho các mục đích khác như Object-To-Dictionary-Serialization và DI Framework – aryaxt

Trả lời

21

Bạn có thể sử dụng mã này để liệt kê tất cả các thuộc tính được khai báo trong một lớp và tất cả các thuộc tính của thuộc tính. Tôi đoán bạn quan tâm hơn đến việc phân tích cú pháp thuộc tính type. Chúng được chi tiết here.

unsigned int numOfProperties; 
objc_property_t *properties = class_copyPropertyList([self class], &numOfProperties); 
for (unsigned int pi = 0; pi < numOfProperties; pi++) { 
    // Examine the property attributes 
    unsigned int numOfAttributes; 
    objc_property_attribute_t *propertyAttributes = property_copyAttributeList(properties[pi], &numOfAttributes); 
    for (unsigned int ai = 0; ai < numOfAttributes; ai++) { 
     switch (propertyAttributes[ai].name[0]) { 
      case 'T': // type 
       break; 
      case 'R': // readonly 
       break; 
      case 'C': // copy 
       break; 
      case '&': // retain 
       break; 
      case 'N': // nonatomic 
       break; 
      case 'G': // custom getter 
       break; 
      case 'S': // custom setter 
       break; 
      case 'D': // dynamic 
       break; 
      default: 
       break; 
     } 
    } 
    free(propertyAttributes); 
} 
free(properties); 
+1

Lưu ý rằng không có định nghĩa hợp lý nào về các tên khác nhau được trưng ra vì một lý do; nó là một chi tiết triển khai có thể thay đổi trong tương lai. – bbum

+0

@bbum Đồng ý, nhưng thông tin được hiển thị đủ hữu ích để tạo ra các phương thức truy cập cho các thuộc tính động trong thời gian chạy. – Costique

+0

@Costique về việc giải phóng chuỗi .name, .value trong mọi thuộc tính trong mảng thuộc tính? Ai có quyền sở hữu đối với họ, thời gian chạy hoặc nhà phát triển? – Andy

1

Có thể class_copyPropertyList() sẽ làm những gì bạn đang theo dõi - nhưng lưu ý rằng nó chỉ trả về các thuộc tính đã khai báo.

Không phải tất cả các thuộc tính đều được khai báo - NSDictionaryNSMutableDictionary là ví dụ về các lớp nơi bạn có thể đặt thuộc tính không được khai báo trong lớp.

Tìm hiểu thêm trong số docs.

2

tôi sử dụng loại sau trên NSObject để nói, ví dụ, NSLog(@"%@", [someObject propertiesPlease]);, kết quả là một bản ghi như ...

someObject: { 
    color = "NSCalibratedRGBColorSpace 0 0 1 1"; 
    crayon = Blueberry; 
} 

NSObject + Additions.h

@interface NSObject (Additions) 
- (NSDictionary *)propertiesPlease; 
@end 

NSObject + Bổ sung.m

@implementation NSObject (Additions) 
- (NSDictionary *)propertiesPlease { 
NSMutableDictionary *props = [NSMutableDictionary dictionary]; 
unsigned int outCount, i; 
objc_property_t *properties = class_copyPropertyList([self class], &outCount); 
for (i = 0; i < outCount; i++) { 
    objc_property_t property = properties[i]; 
    NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property)]; 
    id propertyValue = [self valueForKey:(NSString *)propertyName]; 
    if (propertyValue) [props setObject:propertyValue forKey:propertyName]; 
} 
    free(properties); 
    return props; 
} 
@end 
+1

Ôi trời ơi, cảm giác quá bẩn thỉu ... – buildsucceeded

+1

initWithCString không được dùng nữa, [[NSString alloc] initWithBytes: property_getName (thuộc tính) length: strlen (property_getName (property)) encoding: NSUTF8StringEncoding] sẽ hoạt động thay thế. –

+0

Giá trị trả về của 'property_getName' có được miễn phí không? –

0

Tôi chưa có đặc quyền nhận xét, nhưng để thêm vào câu trả lời của @ Costique, có thêm thuộc tính Loại giá trị "V" là tên của IVar mà tài sản có thể bị ràng buộc (thông qua tổng hợp). Điều này có thể dễ dàng phát hiện ra với điều này

@ interface Redacted: NSObject

@property (nguyên tử, chỉ đọc) int foo;

@end


@implementation Redacted

@synthesize foo = foobar;

@end

// for all properties 
unsigned propertyCount = 0; 
objc_property_t *properties = class_copyPropertyList([object class], &propertyCount); 
for (int prop = 0; prop < propertyCount; prop++) 
{ 
    // for all property attributes 
    unsigned int attributeCount = 0; 
    objc_property_attribute_t* attributes = property_copyAttributeList(property, &attributeCount); 
    for (unsigned int attr = 0; attr < attributeCount; attr++) 
    { 
     NSLog(@"Attribute %d: name: %s, value: %s", attr, attributes[attr].name, attributes[attr].value); 
    } 
} 

2013-07-08 13: 47: 16,600 Redacted5162: 303] Thuộc tính 0: Tên: T, giá trị: i

2013-07-08 13 : 47: 16.601 Đã chỉnh sửa [5162: 303] Thuộc tính 1: tên: R, giá trị:

2013-07-08 13:47:16.602 Redacted [5162: 303] Thuộc tính 2: tên: V, giá trị: fooBar

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