2012-05-17 27 views
11

Khi tôi tuyên bố một tài sản, tôi có thể đặt thuộc tính khác nhau trong việc kê khai, trong đó sẽ có ý nghĩa đặc biệt đối với trình biên dịch:Tôi có thể chỉ định các thuộc tính tùy chỉnh trên các thành viên trong Objective-C không?

@property (nonatomic, retain) NSNumber *consumption; 

Ở đây, nonatomicretain là các thuộc tính. Có thể thêm thuộc tính tùy chỉnh và có thể kiểm tra sự tồn tại của thuộc tính này khi chạy không? Ví dụ:

@property (nonatomic, retain, test) NSNumber* consumption; 

Tôi cơ bản sử dụng cho một cấu trúc có thể thay thế việc sử dụng các thuộc tính như tôi biết từ C# /. NET - vì vậy đề xuất thay thế cũng được hoan nghênh.

+1

http://stackoverflow.com/questions/4919021/custom-property-attributes-in-objective-c – rishi

+0

@rishi, cảm ơn, nhưng tôi không thực sự hài lòng với câu trả lời cho câu hỏi đó, vì tình hình cụ thể của tôi không không cho phép tôi tạo một kiểu trả về khác. Tôi đang tìm kiếm câu trả lời cho dù có hay không - và nếu có, thì làm thế nào. – driis

+0

Thật không may là không sửa đổi trình biên dịch. –

Trả lời

4

Bạn không thể thêm thuộc tính vào @property() mà không sửa đổi trình biên dịch.

Lưu ý rằng, nói chung, hãy cắt giảm ngay cả các thuộc tính hiện tại của các khai báo @property khi chạy là hoàn toàn không được khuyến khích. Thời gian chạy không cung cấp API thông qua đó bạn có thể làm như vậy, nhưng nó không dành cho mục đích sử dụng chung và có thể sẽ thay đổi trong tương lai.

+0

Tôi chỉ thực hiện một phương thức lặp qua tất cả các thuộc tính của một lớp và tự động tạo một ánh xạ RestKit. Tại sao grubbing thông qua tài sản chán nản? – Nick

+0

@Nick Rất mong manh. Ai đó có thể tùy ý thêm thuộc tính thông qua danh mục hoặc trong một siêu lớp. Hoặc ai đó có thể tạo ra một cặp phương thức setter/getter mà không cần khai báo thuộc tính. Hoặc người ta có thể tuyên bố một tài sản không có ý định tham gia vào bản đồ RestKit của bạn. Các vấn đề khác đối với người triển khai khung công cụ hơn là các ứng dụng kết thúc, nhưng bạn có thể thấy rằng có phương thức truy vấn kiểu "+ (NSArray *) attributesParticipatingInRestMapping" rõ ràng sẽ giảm đau đầu bảo trì theo thời gian. Yêu cầu các dev để thêm vào đó thiết lập bằng tay không phải là terribly nặng và nó là tự tài liệu. – bbum

0

Bạn luôn có thể thêm tên NSDictionary của tên thuộc tính vào NSArray của thuộc tính. Điều này có thể được lưu trữ trong một lớp cơ sở hoặc một lớp riêng biệt được liên kết với đối tượng ban đầu thông qua API objc_setAssociatedObjects và objc_getAssociatedObjects.

Xem here để biết thông tin về các API này. Nó không chính xác những gì bạn đang tìm kiếm vì bạn sẽ cần phải thay đổi trình biên dịch, nhưng là một cách để thêm siêu dữ liệu cho bất kỳ đối tượng nào.

0

thêm thuộc tính tùy chỉnh vào thuộc tính không phổ biến nhưng tôi mong muốn. tính năng này có thể được sử dụng để tùy chỉnh traversal về các thuộc tính của một lớp. tôi muốn tính năng này khi tôi xử lý SQL: nếu chúng ta có các thuộc tính như: EXCLUDE_FROM_SELECT, INCLUDE_BY_INSERT, EXCLUDE_FROM_UPDATE ... thì nó sẽ rất đẹp.

Thực ra, tôi không chắc chắn có cách nào để bật tính năng này cho chỉ thị @property hay không. tuy nhiên, chúng tôi có thể có thể làm một việc tương tự:

nếu bạn xem objc/runtime.h bạn có thể tìm thấy hàm: class_replaceProperty, không được ghi trong trang web chính thức. một hàm tương tự được gọi là class_addProperty được ghi lại và có thể giúp bạn hiểu được đối số của phiên bản trước đó. Trên thực tế, tôi nghĩ rằng @property sử dụng các chức năng này để thực hiện các thiết lập thuộc tính (nhưng tôi không thể chứng minh được nó).

bạn cũng có thể cần các chức năng sau:

void class_copyPropertyList(...); 
void property_copyAttributeList(...); 
void class_getProperty(...); 

bằng cách sử dụng các chức năng này, bạn có thể làm điều gì đó gì @property thực hiện.

gì tôi đã làm cho vấn đề SQL trước là xác định 3 chức năng để đăng ký tùy chỉnh thuộc tính:

void prepareClass(...); 
void registerAttributes(...); 
void endRegister(...); 

Và sau đó chúng ta có thể thực hiện đăng ký trong +initialize chức năng của lớp tagart của bạn.

Tuy nhiên, việc sử dụng mã (so với khai báo @property @property đơn giản) có thể không phải là giải pháp tốt nhất của bạn, vì chúng tôi có thể muốn xem cài đặt thuộc tính trực tiếp từ khai báo.Và trên thực tế chúng ta có thể làm điều đó tốt hơn bằng cách sử dụng __attribute__((constructor)) và macro:

các @end @ interface thực sự cho phép bạn làm điều này:

@interface MyVO : NSObject 
__attribute__((constructor)) 
void prepareForMyVO(){ prepareClass(MyVO);} 
@property (strong) id p1; 
__attribute__((constructor)) 
static void registerAttrForP1(){ registerAttributes("p1", EXCLUDE_FROM_SELECT);} 
@property (strong) id p2; 
__attribute__((constructor)) 
static void registerAttrForP2(){ registerAttributes("p2", INCLUDE_BY_INSERT);} 
@end 
__attribute__((constructor)) 
static void endRegisterForMyOV(){ endRegister();}; 

do đó, bạn có thể định nghĩa các macro của bạn để xử lý hardcode này:

#define $p(clazz, zuper) class : zuper \ 
__attribute__((constructor)) static void prepareFor ## clazz(){ prepareClass(#MyVO);} 
#define $r(p, attr) p; \ 
__attribute__((constructor)) static void registerAttrFor ## p(){ registerAttributes(#p, attr);} 
#define $e(clazz) __attribute__((constructor)) static void endRegister ## clazz(){ endRegister();}; 



@interface $p(MyVO, NSObject) 
@property (strong) id $r(p1, EXCLUDE_FROM_SELECT); 
@property (strong) id $r(p1, INCLUDE_BY_INSERT); 

@end $e(MyVO) 

PS: mã hóa ở trên không phải là mã hóa chính xác, nó chỉ là một ví dụ. Và tôi không chắc liệu giải pháp macro cuối cùng có hoạt động hay không hy vọng điều này có thể hữu ích.

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