ETA: @DougW một cách chính xác chỉ ra rằng hình thức sở hữu của tài sản (assign
/retain
/copy
) không ảnh hưởng đến getter. Nó vẫn ảnh hưởng đến setter. Đối với loại readonly
, điều này quan trọng nếu bạn định ghi đè phần readonly
của khai báo trong một tiện ích mở rộng lớp, do đó bạn có thể sử dụng trình thiết lập trong quá trình triển khai của mình. Ghi đè thuộc tính tiện ích mở rộng lớp chỉ được phép thay đổi trạng thái readonly
của thuộc tính, do đó phần còn lại của nó - có nghĩa là loại nguyên tử và quyền sở hữu - phải được khai báo thích hợp trong tiêu đề. Ngay cả khi bạn không ghi đè thuộc tính ngay bây giờ, bạn có thể trong tương lai, vì vậy bạn cũng có thể ghi lại cách bạn muốn bộ nhớ được quản lý cho chính mình bằng cách sử dụng tùy chọn chính xác để bắt đầu.
Tính tham chiếu tự động (ARC) thay đổi chi tiết triển khai thời gian chạy bằng cách chồng các quy tắc quản lý bộ nhớ của riêng nó lên trên các quy tắc truy cập cổ điển.
Tại sao sử dụng retain
với readonly
? Nếu bạn đánh dấu một tài sản như retain
, các accessor tổng hợp làm một cái gì đó như thế này:
/* getter for retain property */
- (NSString *)name {
return [[name retain] autorelease];
}
Bây giờ, nếu đối tượng bạn gửi -name
để thay đổi tên trong khi bạn vẫn đang sử dụng nó, mã gọi vẫn sẽ có một tham chiếu hợp lệ cho một chuỗi.Nếu bạn tuyên bố nó như assign
, tuy nhiên, nó sẽ là như thế này:
/* getter for assign property */
- (NSString *)name {
return name;
}
Bây giờ, càng sớm càng tên được thay đổi bởi các đối tượng, nó sẽ phải được phát hành để tránh rò rỉ, mà sẽ làm mất hiệu lực gọi tham chiếu mã. retain
/copy
/assign
thực sự nêu rõ chính sách quản lý bộ nhớ: retain
/copy
nói, "Tôi hứa rằng tôi giữ tham chiếu đến bản gốc/bản sao giá trị tôi cung cấp tại đây", trong khi assign
nói, "Tôi chỉ có giá trị và yêu cầu không sở hữu tham chiếu đến điều này ".
Khi giá trị không cần quản lý bộ nhớ, chẳng hạn như đồng bằng int
, thì assign
có ý nghĩa. Khi bạn cố ý không giữ lại một vật thể, chẳng hạn như một đại biểu, thì assign
sẽ có ý nghĩa. Tuy nhiên, trong hầu hết các trường hợp khác, bạn sẽ muốn retain
hoặc copy
.
Hơn nữa, tệp triển khai chỉ có thể ghi đè phần readwrite
/readonly
của khai báo thuộc tính, không phải phần quản lý bộ nhớ. Như tuyên bố, các tập tin .m
có thể có:
setters
@interface Holiday (/*class extension*/)
@property(nonatomic, retain, readwrite) NSDate *date;
/* override other properties to make them readwrite... */
@end
ngoài công lập cho các tờ khai tài sản ghi đè sau đó sẽ được tổng hợp cùng với các bộ truy xuất nào.
Tại sao không sử dụng người định cư/người truy cập trong thời gian -init
? Bởi vì người định cư/người truy cập thường xuyên thực hiện thông báo KVO, bạn muốn tránh khi đối tượng của bạn không được khởi tạo đầy đủ, tức là trong thời gian -init
(khi nó được khởi tạo một nửa trên đường khởi tạo đầy đủ) và -dealloc
(khi nó được khởi tạo một nửa) cách hoàn toàn không được khởi tạo).
Tại sao sử dụng copy
với readonly
? Để trả lời câu hỏi đầu tiên của bạn: bởi vì nếu copy
so với retain
so với assign
sẽ ảnh hưởng đến cả người định cư và getters. Một getter bản sao sẽ trông như thế này:
/* getter for copy property */
- (NSString *)name {
return [[name copy] autorelease];
}
Tại sao đôi khi copy
và đôi khi retain
?copy
thường được sử dụng với các đối tượng giá trị (đối tượng thụ động đại diện cho một giá trị); retain
thường được sử dụng với các đối tượng khác. Đôi khi, các mối quan tâm về hiệu quả hoạt động (rất có thể là sớm ...) và bạn có thể chọn sử dụng retain
nơi bạn thường sử dụng copy
.
Bạn sử dụng copy
/retain
cùng với readonly
tại đây như thế nào? Khá nhiều như họ đã làm. Tôi muốn ghi đè lên các khai báo trong một phần mở rộng lớp để tôi có thể sử dụng setters để thay đổi các giá trị của thuộc tính bên ngoài của -init
và -dealloc
, nơi tôi sẽ chỉ sử dụng truy cập biến cá thể trực tiếp. Tôi cũng nil
ra ivars sau khi phát hành chúng trong -dealloc
, ví dụ,
[name release], name = nil;
Điều này giúp tránh việc gửi tin nhắn đến hoặc tham khảo một đối tượng đã phát hành.
** nonatomic ** giữ lại thuộc tính chỉ trả về con trỏ. Họ ** không ** làm việc lưu giữ, điều tự động. Xem phần ** atomicity ** của tài liệu http://developer.apple.com/library/ios/# documentation/cocoa/Khái niệm/ObjectiveC/Các bài viết/ocProperties.html – JeremyP
@JeremyP: Cuộc gọi tốt. Quyết định không để '[[giữ lại] autorelease]' trong các truy cập không nguyên tử có ý nghĩa: Nếu bạn định giữ giá trị lâu hơn chu kỳ runloop hiện tại, bạn nên tự giữ lại nó. Nếu bạn đang sử dụng 'nonatomic', về cơ bản bạn nói rằng thread-safety không phải là một mối quan tâm. Nếu bạn không phải lo lắng về thread-safety, thì không có mã nào ngoài bạn sẽ thực thi trong khi bạn đang sử dụng giá trị trả về từ accessor, do đó không cần thiết cho accessor thực hiện '[[foo retain] autorelease]' . –
@Jeremy: Tôi sẽ đi xa như vậy để nói rằng bằng cách sử dụng nonatomic có nghĩa là bạn đang nói rằng sự mạnh mẽ không phải là một mối quan tâm - hoặc ít quan tâm hơn hiệu suất. Đặt các thuộc tính thành nonatomic mà không cần phải tính toán số lượng mã của bạn trước tiên như là một tối ưu hóa sớm trong cuốn sách của tôi. – JeremyP