2010-06-19 35 views
102

Các thuộc tính trong Objective-C 2.0 có yêu cầu một biến cá thể tương ứng được khai báo không? Ví dụ, tôi đang sử dụng để làm một cái gì đó như thế này:Thuộc tính được khai báo có yêu cầu một biến mẫu tương ứng không?

MyObject.h

@interface MyObject : NSObject { 
NSString *name; 
} 
@property (nonatomic, retain) NSString *name; 
@end 

MyObject.m

@implementation 
@synthesize name; 
@end 

Tuy nhiên, những gì nếu tôi đã làm điều này thay vì:

MyObject.h

@interface MyObject : NSObject { 
} 
@property (nonatomic, retain) NSString *name; 
@end 

Điều này vẫn hợp lệ? Và có cách nào khác với ví dụ trước của tôi không?

+0

Tại sao 'MyObject.h' in đậm 'MyObject.m'? –

Trả lời

94

Nếu bạn đang sử dụng Runtime Objective-C Runtime (đó là iOS 3.x trở lên hoặc Snow Leopard 64 bit trở lên) thì bạn cần không phải là số cần xác định ivars cho thuộc tính của bạn trong trường hợp như thế này .

Khi bạn @synthesize thuộc tính, ivar sẽ có hiệu lực cũng được tổng hợp cho bạn. Điều này xung quanh kịch bản "mong manh-ivar". Bạn có thể đọc thêm về nó trên Cocoa with Love

69

Trong giao diện, bạn có thể chính thức khai báo biến mẫu giữa các dấu ngoặc hoặc qua @property bên ngoài dấu ngoặc ôm hoặc cả hai. Dù bằng cách nào, họ trở thành thuộc tính của lớp. Sự khác biệt là nếu bạn khai báo @property, khi đó bạn có thể triển khai bằng cách sử dụng @synthesize, tính năng này tự động mã hóa trình lấy/đặt hàng cho bạn. Ví dụ, bộ đặt mã tự động khởi tạo các số nguyên và số float. NẾU bạn khai báo một biến cá thể, và KHÔNG chỉ định @property tương ứng, thì bạn không thể sử dụng @synthesizephải viết trình khởi động/thiết lập của riêng bạn.

Bạn luôn có thể ghi đè trình khởi động/thiết lập được mã hóa tự động bằng cách chỉ định của riêng bạn. Điều này thường được thực hiện với thuộc tính managedObjectContext được tải nhẹ nhàng. Do đó, bạn khai báo managedObjectContext làm thuộc tính, nhưng sau đó cũng viết phương thức -(NSManagedObjectContext *)managedObjectContext. Nhớ lại rằng một phương thức, có cùng tên như một biến cá thể/thuộc tính là phương thức "getter".

Phương thức khai báo @property cũng cho phép bạn các tùy chọn khác, chẳng hạn như retainreadonly, mà phương pháp khai báo biến cá thể thì không. Về cơ bản, ivar là cách cũ và @property mở rộng nó và làm cho nó trở nên hấp dẫn/dễ dàng hơn. Bạn có thể tham khảo hoặc sử dụng tự. tiền tố, hay không, nó không quan trọng miễn là tên là duy nhất cho lớp đó. Nếu không, nếu lớp cha của bạn có cùng tên của thuộc tính với bạn, thì bạn phải nói giống như self.name hoặc super.name để chỉ định tên bạn đang nói đến.

Vì vậy, bạn sẽ thấy ngày càng ít người tuyên bố ivar s giữa niềng răng, và thay vào đó chuyển hướng chỉ quy định cụ thể @property, và sau đó làm @synthesize. Bạn không thể thực hiện @synthesize trong quá trình triển khai của mình mà không cần tương ứng @property. Trình tổng hợp chỉ biết loại thuộc tính là gì từ đặc điểm kỹ thuật @property.Câu lệnh tổng hợp cũng cho phép bạn đổi tên thuộc tính, để bạn có thể tham chiếu đến một thuộc tính bằng một tên (viết tắt) bên trong mã của bạn, nhưng bên ngoài trong tệp .h sử dụng tên đầy đủ. Tuy nhiên, với tính năng tự động hoàn thành thực sự tuyệt vời mà XCode hiện có, đây là một lợi thế nhỏ nhưng vẫn còn đó.

Hy vọng điều này sẽ giúp làm sáng tỏ tất cả sự nhầm lẫn và thông tin sai lệch trôi nổi xung quanh đó.

+3

Giải thích tuyệt vời .. –

+0

thực sự tuyệt vời – Fab1n

+1

Câu trả lời này đã xóa các tuần lộn xộn đối với tôi! –

3

Từ các tài liệu:

Nói chung hành vi của thuộc tính là giống hệt nhau trên cả hai runtimes hiện đại và di sản (xem “Thời gian chạy phiên bản và nền tảng” trong Objective-C Runtime Programming Guide). Có một sự khác biệt chính: thời gian chạy hiện đại hỗ trợ tổng hợp biến thể trong khi thời gian chạy kế thừa không.

Để @synthesize hoạt động trong thời gian chạy cũ, bạn phải cung cấp biến mẫu có cùng tên và loại tương thích của thuộc tính hoặc chỉ định một biến mẫu hiện có khác trong câu lệnh @synthesize. Với thời gian chạy hiện đại, nếu bạn không cung cấp một biến mẫu, trình biên dịch sẽ thêm một biến cho bạn.

8

nó hoạt động theo cả hai cách nhưng nếu bạn không khai báo chúng trong dấu ngoặc nhọn, bạn sẽ không thấy giá trị của chúng trong trình gỡ lỗi trong xcode.

1

The Objective-C Programming Language: Property Implementation Directives

Có sự khác biệt trong hành vi của tổng hợp accessor mà phụ thuộc vào thời gian chạy (xem thêm “Runtime Difference”):

  • Đối với các runtimes di sản, các biến Ví dụ phải đã được khai báo trong khối @interface của lớp hiện tại. Nếu một biến mẫu có cùng tên với thuộc tính tồn tại và nếu loại của nó tương thích với loại thuộc tính thì nó được sử dụng — nếu không, bạn sẽ gặp lỗi trình biên dịch.

  • Đối với các thời gian chạy hiện đại (xem “Phiên bản thời gian và nền tảng” trong Hướng dẫn lập trình thời gian chạy mục tiêu-C), các biến mẫu được tổng hợp khi cần. Nếu một biến mẫu cùng tên đã tồn tại, nó được sử dụng.

3

Nếu bạn đang sử dụng XCode 4.4 trở lên, nó sẽ tạo mã tổng hợp biến mẫu cho bạn.

Bạn chỉ cần khai báo các thuộc tính như dưới đây; nó sẽ tạo ra mã tổng hợp và mã khai báo biến mẫu cho bạn.

@property (nonatomic, strong) NSString *name; 

nó sẽ tạo ra tổng hợp mã như

@synthesize name = _name; 

và bạn có thể truy cập vào biến dụ sử dụng _name nó cũng tương tự như tuyên bố

NSString* _name 

nhưng nếu bạn khai báo thuộc tính chỉ đọc nó như

@property (nonatomic, strong, readonly) NSString *name; 

nó sẽ tạo ra mã

@synthesize name; 

hoặc

@synthesize name = name; 

Vì vậy, bạn nên truy cập vào tên biến tức thì với tiền tố ra "_" bất kỳ cách nào bạn có thể viết mã tổng hợp của riêng bạn sau đó trình biên dịch sẽ tạo ra mã cho bạn. bạn có thể viết

@synthesize name = _name; 
Các vấn đề liên quan