Các LLVM Compiler 3.0 giới thiệu Bốn vòng loại quyền sở hữu mới: __strong
, __autoreleasing
, __unsafe_unretained
, và __weak
. Ba đầu tiên có sẵn ngay cả bên ngoài ARC, theo thông số kỹ thuật .
Như Joshua chỉ ra, theo mặc định, tất cả các con trỏ được ngụ ý là __strong
nằm trong ARC. Điều này có nghĩa là khi một đối tượng được gán cho con trỏ đó, nó được giữ lại miễn là con trỏ đó tham chiếu đến nó. Điều này tốt cho hầu hết mọi thứ, nhưng nó mở ra khả năng cho các chu kỳ lưu giữ, như tôi mô tả trong câu trả lời của tôi ở đây . Ví dụ: nếu bạn có một đối tượng chứa một đối tượng khác như một biến thể hiện, nhưng đối tượng thứ hai đó có một liên kết mạnh trở lại đối tượng đầu tiên làm đại biểu của nó, thì hai đối tượng sẽ không bao giờ được giải phóng.
Đó là vì lý do này mà các __unsafe_unretained
và các __weak
vòng loại tồn tại. Cách sử dụng phổ biến nhất của chúng là cho các đại biểu, nơi bạn sẽ xác định một thuộc tính cho đại biểu đó với thuộc tính weak
hoặc unsafe_unretained
( assign
là hiệu quả unsafe_unretained
), sau đó khớp với thuộc tính đó bằng cách đánh dấu biến phiên bản tương ứng bằng __weak
hoặc __unsafe_unretained
. Điều này có nghĩa là biến thể hiện đại biểu sẽ vẫn trỏ trở lại đối tượng đầu tiên, nhưng nó sẽ không khiến đối tượng đó được giữ lại, do đó phá vỡ chu kỳ giữ lại và cho phép cả hai đối tượng được giải phóng.
Ngoài các đại biểu, điều này hữu ích để phá vỡ bất kỳ chu kỳ lưu giữ nào khác có thể hình thành trong mã của bạn. Một cách hữu ích, công cụ Rò rỉ giờ đây bao gồm chế độ xem Chu kỳ, hiển thị các chu kỳ lưu giữ mà nó phát hiện ra trong ứng dụng của bạn dưới dạng đồ họa.
Cả hai __unsafe_unretained
và __weak
ngăn chặn việc giữ lại các đối tượng, nhưng theo những cách hơi khác nhau. Đối với __weak
, con trỏ tới một đối tượng sẽ chuyển đổi sang vị nil
trí giao dịch của đối tượng mà nó trỏ tới, đây là hành vi rất an toàn. Như tên của nó, __unsafe_unretained
sẽ tiếp tục trỏ đến bộ nhớ nơi một đối tượng đã ở đó, ngay cả sau khi nó đã được định vị. Điều này có thể dẫn đến sự cố do truy cập đối tượng được phân bổ theo thỏa thuận đó.
Tại sao bạn sẽ sử dụng __unsafe_unretained
sau đó? Thật không may, __weak
chỉ được hỗ trợ cho iOS 5.0 và Lion làm mục tiêu triển khai. Nếu bạn muốn nhắm mục tiêu trở lại iOS 4.0 và Snow Leopard, bạn phải sử dụng bộ định lượng __unsafe_unretained
hoặc sử dụng cái gì đó như MAZeroingWeakRef của Mike Ash .
__unsafe_unretained
có thể hữu ích cho việc xác định các mảng CNSString
hằng số và những thứ tương tự, ví dụ:NSString __unsafe_unretained *myStrings = { @"Foo", @"Bar", @"Baz", nil };