Cũng cần nhớ rằng chu kỳ giữ lại có thể xảy ra nếu khối của bạn tham chiếu đến một đối tượng khác mà sau đó giữ lại self
.
Tôi không chắc chắn rằng Bộ sưu tập rác có thể giúp ích trong các chu kỳ giữ lại này. Nếu đối tượng giữ lại khối (mà tôi sẽ gọi đối tượng máy chủ) tồn tại self
(đối tượng khách), thì tham chiếu self
bên trong khối sẽ không được coi là tuần hoàn cho đến khi chính đối tượng giữ lại được giải phóng. Nếu đối tượng máy chủ vượt xa các máy khách của nó, bạn có thể bị rò rỉ bộ nhớ đáng kể.
Vì không có giải pháp sạch, tôi sẽ đề xuất các cách giải quyết sau. Hãy chọn một hoặc nhiều trong số họ để khắc phục vấn đề của bạn.
- Chỉ sử dụng các khối để hoàn thành và không cho các sự kiện kết thúc mở. Ví dụ: sử dụng các khối cho các phương thức như
doSomethingAndWhenDoneExecuteThisBlock:
, chứ không phải các phương thức như setNotificationHandlerBlock:
. Các khối được sử dụng để hoàn thành có thời gian kết thúc xác định và sẽ được các đối tượng máy chủ giải phóng sau khi chúng được đánh giá. Điều này ngăn chặn chu kỳ giữ lại sống quá lâu ngay cả khi nó xảy ra.
- Làm điệu nhảy tham chiếu yếu mà bạn mô tả.
- Cung cấp một phương thức để dọn sạch đối tượng của bạn trước khi nó được phát hành, nó "ngắt kết nối" đối tượng khỏi các đối tượng máy chủ có thể chứa các tham chiếu đến nó; và gọi phương thức này trước khi gọi phát hành trên đối tượng. Mặc dù phương pháp này hoàn toàn tốt nếu đối tượng của bạn chỉ có một khách hàng (hoặc là một người độc thân trong một số ngữ cảnh), nhưng sẽ bị hỏng nếu có nhiều khách hàng. Về cơ bản bạn đang đánh bại cơ chế đếm giữ ở đây; đây là giống như gọi
dealloc
thay vì release
.
Nếu bạn đang viết một đối tượng máy chủ, chỉ lấy các đối số khối để hoàn thành. Không chấp nhận đối số khối cho các cuộc gọi lại, chẳng hạn như setEventHandlerBlock:
. Thay vào đó, hãy quay lại mô hình đại biểu cổ điển: tạo một giao thức chính thức và quảng cáo một setEventDelegate:
phương thức. Không giữ lại đại biểu. Nếu bạn thậm chí không muốn tạo một giao thức chính thức, hãy chấp nhận bộ chọn làm cuộc gọi lại ủy nhiệm.
Và cuối cùng, mẫu này sẽ rung chuông báo động:
- (void) dealloc {
[myServerObject phát hànhCallbackBlocksForObject: self];
...
}
Nếu bạn đang cố gắng mở các khối có thể tham chiếu self
từ bên trong dealloc
, bạn đã gặp rắc rối. dealloc
có thể không bao giờ được gọi do chu kỳ giữ lại gây ra bởi các tham chiếu trong khối, điều đó có nghĩa là đối tượng của bạn chỉ đơn giản là bị rò rỉ cho đến khi đối tượng máy chủ bị hủy.
self
proxy của tôithis
chỉ để lật mọi thứ xung quanh. Trong JavaScript tôi gọi các baothis
đóng của tôiself
, vì vậy nó cảm thấy tốt và cân bằng. :)