2011-10-19 58 views

Trả lời

60

Có thể thêm các thuộc tính chính thức cho một lớp học qua class_addProperty():

BOOL class_addProperty(Class cls, 
    const char *name, 
    const objc_property_attribute_t *attributes, 
    unsigned int attributeCount) 

Hai thông số đầu tiên là tự giải thích. Tham số thứ ba là một mảng thuộc tính thuộc tính và mỗi thuộc tính thuộc tính là cặp tên-giá trị theo Mục tiêu-C type encodings cho declared properties. Lưu ý rằng tài liệu vẫn đề cập đến chuỗi được phân tách bằng dấu phẩy cho việc mã hóa thuộc tính thuộc tính. Mỗi phân đoạn trong chuỗi được phân tách bằng dấu phẩy được thể hiện bằng một ví dụ objc_property_attribute_t. Ngoài ra, objc_property_attribute_t chấp nhận tên lớp ngoài mã hóa loại @ chung của id.

Dưới đây là một dự thảo đầu tiên của một chương trình tự động bổ sung thêm một tính chất gọi là name đến một lớp học mà đã có một biến Ví dụ gọi _privateName:

#include <objc/runtime.h> 
#import <Foundation/Foundation.h> 

@interface SomeClass : NSObject { 
    NSString *_privateName; 
} 
@end 

@implementation SomeClass 
- (id)init { 
    self = [super init]; 
    if (self) _privateName = @"Steve"; 
    return self; 
} 
@end 

NSString *nameGetter(id self, SEL _cmd) { 
    Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName"); 
    return object_getIvar(self, ivar); 
} 

void nameSetter(id self, SEL _cmd, NSString *newName) { 
    Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName"); 
    id oldName = object_getIvar(self, ivar); 
    if (oldName != newName) object_setIvar(self, ivar, [newName copy]); 
} 

int main(void) { 
    @autoreleasepool { 
     objc_property_attribute_t type = { "T", "@\"NSString\"" }; 
     objc_property_attribute_t ownership = { "C", "" }; // C = copy 
     objc_property_attribute_t backingivar = { "V", "_privateName" }; 
     objc_property_attribute_t attrs[] = { type, ownership, backingivar }; 
     class_addProperty([SomeClass class], "name", attrs, 3); 
     class_addMethod([SomeClass class], @selector(name), (IMP)nameGetter, "@@:"); 
     class_addMethod([SomeClass class], @selector(setName:), (IMP)nameSetter, "[email protected]:@"); 

     id o = [SomeClass new]; 
     NSLog(@"%@", [o name]); 
     [o setName:@"Jobs"]; 
     NSLog(@"%@", [o name]); 
    } 
} 

của nó (tỉa) đầu ra:

Steve 
Jobs 

Các phương thức getter và setter nên được viết cẩn thận hơn nhưng điều này đủ để làm ví dụ về cách tự động thêm một thuộc tính chính thức khi chạy.

+1

class_addProperty trả về true, nhưng class_getInstanceVariable luôn trả về 0. Tôi đã thử đặt tên thuộc tính thay vì tên ngà, nhưng vẫn không có may mắn. Bất kỳ ý tưởng gì có thể là vấn đề? – Mercurial

+1

@Bavarious, bạn đánh lừa như thế nào? Tôi có nghĩa là [o tên] kết quả trong lỗi biên dịch 'Không có phương pháp ví dụ nào cho tên bộ chọn' '. –

+0

@HiteshSavaliya một thời gian dài trước đây (trước ARC) điều này là có thể. ngày nay bạn phải khai báo bộ chọn '-name'. – Michael

8

Nếu bạn có một cái nhìn tại NSKeyValueCoding giao thức, tài liệu here, bạn có thể thấy rằng có một thông điệp kêu gọi:

- (id)valueForUndefinedKey:(NSString *)key 

Bạn nên ghi đè lên rằng phương pháp để cung cấp kết quả tùy chỉnh của bạn cho các tài sản không xác định cụ thể. Tất nhiên điều này giả định rằng lớp của bạn sử dụng giao thức tương ứng.

Cách tiếp cận này thường được sử dụng để cung cấp hành vi không xác định cho các lớp (ví dụ: bộ chọn không tồn tại).

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