2011-12-21 53 views
67

Chỉ muốn chắc chắn rằng tôi đã nhận nó đúng:ARC - Ý nghĩa của __unsafe_unretained?

  1. Tôi có cần phải __unsafe_unretain đối tượng mà tôi không sở hữu?
  2. Nếu một đối tượng là __unsafe_unretained Tôi có cần sử dụng assign trong số @property không? Điều đó có nghĩa là đối tượng không được giữ lại và chỉ đề cập đến đối tượng mà tôi gán cho?
  3. Khi nào tôi muốn sử dụng nó ngoại trừ các đại biểu?
  4. Đây có phải là vật liệu ARC hoặc được sử dụng trước đó không?

Trả lời

172

Trình biên dịch LLVM 3.0 giới thiệu bốn vòng loại quyền sở hữu mới: __strong, __autoreleasing, __unsafe_unretained__weak. Ba số đầu tiên khả dụng ngay cả bên ngoài ARC, theo số the specification.

Như Joshua cho biết, theo mặc định, tất cả các con trỏ được ngụ ý là __strong 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ỏ đó đề cập đến nó. Điều này là tốt cho hầu hết mọi thứ, nhưng nó mở ra khả năng giữ lại chu kỳ, như tôi mô tả trong câu trả lời của tôi here. Ví dụ, nếu bạn có một đối tượng có chứa một đối tượng khác như một biến cá thể, 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ó, hai đối tượng sẽ không bao giờ được giải phóng.

Đó là vì lý do này tồn tại vòng loại __unsafe_unretained__weak. Cách sử dụng phổ biến nhất của họ là dành cho đại biểu, nơi bạn muốn xác định 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) và sau đó so khớp nó bằng cách đánh dấu biến mẫu tương ứng với __weak hoặc __unsafe_unretained. Điều này có nghĩa là biến cá thể đại biểu vẫn sẽ trỏ ngược 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 trình lưu giữ 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 rất hữu ích để phá vỡ bất kỳ chu kỳ giữ chân 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ỳ, cho thấy các chu kỳ lưu giữ mà nó phát hiện trong ứng dụng của bạn theo cách đồ họa.

Cả hai __unsafe_unretained__weak ngăn việc lưu giữ các đối tượng, nhưng theo những cách hơi khác nhau. Đối với __weak, con trỏ đến một đối tượng sẽ chuyển đổi thành nil trên deallocation của đối tượng nó trỏ đến, đó là hành vi rất an toàn.Như tên gọi của nó, __unsafe_unretained sẽ tiếp tục trỏ đến bộ nhớ có đối tượng, ngay cả sau khi nó được deallocated. Điều này có thể dẫn đến sự cố do truy cập vào đối tượng deallocated đó.

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 loại vòng loại __unsafe_unretained hoặc sử dụng thứ gì đó giống như của Mike Ash MAZeroingWeakRef.

+2

Và tất nhiên '__unsafe_unretained' có thể là hữu ích cho việc xác định các mảng C của 'NSString' hằng số và tương tự, ví dụ 'NSString __unsafe_unretained * myStrings = {@" Foo ", @" Bar ", @" Baz ", nil};' – jlehr

+0

Cảm ơn câu trả lời tuyệt vời. khi tôi sử dụng __unsafe_unretained sẽ iOS tham khảo nó như _weak nếu hệ điều hành thiết bị là 5? hoặc nó được đặt ở thời gian biên dịch trên xCode? – shannoga

+1

@shannoga - Không, bạn phải chỉ định bằng tay '__weak' làm bộ định tính để sử dụng những loại con trỏ đó. Bạn vẫn có thể sử dụng '__unsafe_unretained' với mục tiêu thuần túy là 5.0 và nó sẽ không hoạt động như' __weak'. Nếu bạn muốn một cái gì đó sẽ chuyển đổi giữa hai chế độ tùy thuộc vào việc mục tiêu của bạn có hỗ trợ nó hay không, bạn có thể sử dụng một định nghĩa trình biên dịch cụ thể như tôi đề xuất ở đây: http://stackoverflow.com/a/8594878/19679 –

4
  1. Không, bạn cũng có thể sử dụng weak cho các đối tượng bạn không sở hữu.
  2. Không, bạn cũng có thể sử dụng unsafe_unretained trên thuộc tính.
  3. Sự hiểu biết của tôi là unsafe_unretained các mục giống như weak, mà không có sự an toàn bổ sung để xóa chúng khi mục mà chúng trỏ tới được giải phóng (và chi phí đi kèm với nó).
  4. Đây hoàn toàn là một điều ARC.
+0

Thực ra, kỳ quặc đủ, 'unsafe_unretained' iVars, khi được đặt ở thời gian chạy, hoạt động giống như 'strong', dẫn tôi tin rằng' unsafe_unretained' chỉ đơn giản là gợi ý trình biên dịch, trong khi yếu thì không. Thông tin thêm tại đây: http://stackoverflow.com/questions/11621028/discovering-at-runtime-which-of-a-class-instance-variables-are-declared-weak#comment15389310_11621028 –

4

__unsafe_unretained giống với dung lượng lưu trữ mặc định của đối tượng trước ARC. Với ARC, mặc định là __strong có nghĩa là bạn có tham chiếu đến nó cho đến khi tham chiếu của bạn nằm ngoài phạm vi.

1

Một quan sát khác về __unsafe_unretained: Tôi gặp sự cố trong ứng dụng trên thiết bị và NOT trên trình mô phỏng có iVars được khai báo là __unsafe_unretained! Có, đó là lỗi trong mã từ di chuyển ARC, nhưng đây là lần đầu tiên tôi nhận thấy sự khác biệt như vậy giữa thiết bị và trình mô phỏng.