Các thuộc tính đã khai báo có yêu cầu một biến phiên bản tương ứng không?


101

Các thuộc tính trong Objective-C 2.0 có yêu cầu một biến phiên bản tương ứng được khai báo không? Ví dụ, tôi đã quen với việc làm như thế này:

MyObject.h

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

MyObject.m

@implementation
@synthesize name;
@end

Tuy nhiên, điều gì sẽ xảy ra nếu tôi làm điều này thay thế:

MyObject.h

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

Điều này vẫn còn giá trị? Và nó có khác với ví dụ trước của tôi theo cách nào không?


Tại sao 'MyObject.h' thứ hai được in đậm không phải là 'MyObject.m'?
Ríomhaire

Câu trả lời:


93

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

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


71

Trong giao diện của bạn, bạn có thể chính thức khai báo một biến thể hiện giữa các dấu ngoặc nhọn hoặc thông qua @propertybên ngoài dấu ngoặc nhọn hoặc cả hai. Dù bằng cách nào, chúng cũng 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, thì bạn có thể triển khai bằng cách sử dụng @synthesizetự động mã getter / setter cho bạn. Ví dụ: bộ lập mã tự động khởi tạo số nguyên và thả nổi về 0. NẾU bạn khai báo một biến thể hiện và KHÔNG chỉ định một biến tương ứng @property, thì bạn không thể sử dụng @synthesizephải viết getter / setter của riêng bạn.

Bạn luôn có thể ghi đè getter / setter đượ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 managedObjectContexttính được tải chậm. Vì vậy, bạn khai báo của bạn managedObjectContextlà một thuộc tính, nhưng sau đó cũng viết một -(NSManagedObjectContext *)managedObjectContextphương thức. Nhớ lại rằng một phương thức có cùng tên với một biến / thuộc tính cá thể là phương thức "getter".

Các @propertyphương pháp kê khai cũng cho phép bạn tùy chọn khác, chẳng hạn như retainreadonly, trong đó phương pháp khai báo biến dụ không. Về cơ bản, ivarlà cách cũ, và @propertymở rộng nó và làm cho nó đẹp hơ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, không quan trọng miễn là tên là duy nhất cho lớp đó. Ngược lại, nếu lớp cha của bạn có cùng tên thuộc tính với bạn, thì bạn phải nói như self.name hoặc super.name để chỉ định tên bạn đang nói đến.

Do đó, bạn sẽ thấy ngày càng ít người khai báo ivars giữa các dấu ngoặc nhọn, và thay vào đó chuyển sang chỉ xác định @property, rồi thực hiện @synthesize. Bạn không thể thực hiện @synthesizetrong triển khai của mình mà không có một tương ứng @property. Bộ tổng hợp chỉ biết nó là loại thuộc tính nào từ @propertyđặc tả. 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 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ế ít hơn, nhưng vẫn còn đó.

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


Ngày nay, không bắt buộc phải viết @synthesize. Vậy làm thế nào câu trả lời này hợp lệ trong trường hợp đó!
raaz

Bạn không PHẢI khai báo <code> @property ... @ tổng hợp </code>. Sử dụng tổng hợp giúp bạn giảm bớt việc phải viết getter / setter trong quá trình triển khai của bạn. Nếu bạn không tổng hợp, sau đó bạn phải cuộn getter của riêng bạn / setter
PapaSmurf

2
@PapaSmurf Điều đó không chính xác. Bạn có thể sử dụng @property, không sử dụng @synthesizevà không tự thực hiện chúng. Trình biên dịch sẽ tự động synthesizecho bạn mà không cần phải viết nữa.
jbrennan

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.


3

Từ tài liệu:

Nói chung, hành vi của các thuộc tính giống hệt nhau trên cả thời gian chạy hiện đại và cũ (xem “Các phiên bản và nền tảng thời gian chạy” trong Hướng dẫn lập trình thời gian chạy Objective-C). Có một điểm khác biệt chính: thời gian chạy hiện đại hỗ trợ tổng hợp biến cá thể trong khi thời gian chạy kế thừa thì không.

Để @synthesize hoạt động trong thời gian chạy kế thừa, bạn phải cung cấp một biến phiên bản có cùng tên và kiểu tương thích của thuộc tính hoặc chỉ định một biến phiên bản 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 thể hiện, trình biên dịch sẽ thêm một biến cho bạn.


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 phiên bản 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 mã tổng hợp và mã khai báo biến cá thể cho bạn.

@property (nonatomic, strong) NSString *name;

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

@synthesize name = _name;

và bạn có thể truy cập biến cá thể bằng cách sử dụng _name, nó tương tự như khai báo

NSString* _name

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

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

nó sẽ tạo ra mã

@synthesize name;

hoặc là

@synthesize name = name; 

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

@synthesize name = _name;

1

Ngôn ngữ lập trình Objective-C: Chỉ thị triển khai thuộc tính

Có sự khác biệt trong hành vi tổng hợp trình truy cập phụ thuộc vào thời gian chạy (xem thêm “Sự khác biệt về thời gian chạy”):

  • Đối với các thời gian chạy kế thừa, các biến phiên bản phải được khai báo trong khối @interface của lớp hiện tại. Nếu một biến thể hiện có cùng tên với thuộc tính tồn tại và nếu kiểu của nó tương thích với kiểu của thuộc tính, thì nó sẽ đượ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 “Các phiên bản và nền tảng thời gian chạy” trong Hướng dẫn lập trình thời gian chạy Objective-C), các biến phiên bản được tổng hợp khi cần thiết. Nếu một biến thể hiện có cùng tên đã tồn tại, nó sẽ được sử dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.