2010-12-27 6 views
14

Tôi luôn nghĩ rằng người ta không thể khai báo một thuộc tính đối tượng trong một thể loại. Cho đến khi đối tác của tôi đã làm điều đó trong mã của ứng dụng của chúng tôi, và nó dường như hoạt động.Vì khi nào có thể khai báo các thuộc tính Objective-C 2.0 trong một danh mục?

Tôi đã đi trên một SO và Google binge để cố gắng giải thích cho anh ta rằng không, mục tiêu-C loại chỉ có thể được sử dụng để thêm phương pháp, không phải tài sản. Tôi tìm thấy câu hỏi như:

Nhưng sau đó tôi tìm thấy this link trên trang web của Apple chứa sau đây về việc kê khai @property:

Tuyên bố thuộc tính bắt đầu bằng từ khóa @property. @property có thể xuất hiện ở bất kỳ đâu trong phương thức danh sách khai báo được tìm thấy trong @interface của một lớp học. @property có thể cũng xuất hiện trong tuyên bố của giao thức hoặc danh mục. (Nhấn mạnh thêm)

Tôi biết rằng điều này không làm việc:

@interface MyClass() 
NSInteger foobar; 
- (void) someCategorizedMethod; 
@end 

Nhưng điều này biên dịch:

@interface MyClass() 
@property NSInteger foobar; 
- (void) someCategorizedMethod; 
@end 

Câu hỏi của tôi là (a) thực hành tốt nhất là những gì ở đây? và (b) là cái gì đó mới mẻ đối với mục tiêu-C 2.0, và thay vì sử dụng một iVar "thực", nó đơn giản sử dụng lưu trữ kết hợp đằng sau hậu trường để thực hiện công việc này?

Trả lời

31

Bạn luôn có thể khai báo số @property trong danh mục. Những gì bạn không thể làm - và vẫn không thể - là khai báo lưu trữ cho thuộc tính trong danh mục, không phải là một biến mẫu hoặc cũng không thông qua `@synthesize.

Tuy nhiên ....

@interface MyClass()không phải là một loại. Nó là một phần mở rộng lớp và có một vai trò rõ ràng hơn cụ thể hơn một thể loại.

Cụ thể, tiện ích mở rộng lớp có thể được sử dụng để mở rộng @interface của lớp học và điều này bao gồm @properties có thể được @synthesized (bao gồm tổng hợp bộ nhớ trong thời gian chạy hiện đại).

Foo.h: 

@interface Foo 
@end 

Foo.m: 

@interface Foo() 
@property int x; 
@end 

@implementation Foo 
@synthesize x; // synthesizes methods & storage 
@end 

nó chỉ đơn giản là sử dụng bộ nhớ kết hợp đằng sau hậu trường để làm công việc này?

Không - đây là biến thể hiện thực. Thời gian chạy hiện đại khắc phục sự cố lớp cơ sở mong manh.


@interface MyClass() 
NSInteger foobar; 
- (void) someCategorizedMethod; 
@end 

ở trên không hoạt động (như mong đợi) vì foobar là, có hiệu quả, một biến toàn cầu.

Nếu bạn thay đổi nó để:

@interface MyClass() { 
    NSInteger foobar; 
} 
- (void) someCategorizedMethod; 
@end 

Sau đó, nó sẽ làm việc với phiên bản mới nhất của trình biên dịch llvm (với những lá cờ đúng, như @Joshua chỉ trong một chú thích).

+0

Để thêm vào điều này, ví dụ đầu tiên của anh ta nơi anh ta thêm iVar là hoàn toàn hợp lệ trong llvm với -Xclang -fobjc-nonfragile-abi2 –

+1

Sẽ là nếu anh ta thêm một chiếc ngà. Trong trường hợp đó, anh ta thêm một biến tĩnh không phải là một biến mẫu. – bbum

+0

cảm ơn bạn đã giải thích sâu rộng. Tôi sẽ chia sẻ liên kết này với các đối tác viết mã của tôi !! – makdad

1

Nói chung, các thuộc tính không có gì khác với các phương pháp khác. Miễn là ngà được sử dụng có sẵn trong lớp thông thường, thì hoàn toàn không có vấn đề gì. Nó chỉ là cú pháp.

Mọi thứ trở nên khó khăn hơn nếu cả ivar cũng được tạo tự động, như có thể ở một số cấu hình.

Điểm chính ở đây là tuyên bố của ivar độc lập với tài sản.

1

Lưu trữ Assotiative là giải pháp. Hãy xem post này.

+0

Cảm ơn bạn đã theo dõi - đây thực sự là một cách có thể xung quanh vấn đề này. – makdad