ARC có hỗ trợ hàng đợi gửi không?


95

Tôi đang đọc tài liệu của apple về "Quản lý bộ nhớ cho hàng đợi gửi đi":

Ngay cả khi bạn triển khai một ứng dụng thu gom rác, bạn vẫn phải giữ lại và giải phóng hàng đợi gửi và các đối tượng điều phối khác. Grand Central Dispatch không hỗ trợ mô hình thu gom rác để lấy lại bộ nhớ.

Tôi biết rằng ARC không phải là công cụ thu gom rác nhưng tôi muốn chắc chắn rằng tôi không cần phải gửi đi Dispatch_retain và công văn gửi đi của tôi.

Câu trả lời:


234

Câu trả lời ngắn gọn: CÓ, ARC giữ lại và giải phóng hàng đợi gửi.







Và bây giờ là câu trả lời dài…

Nếu mục tiêu triển khai của bạn thấp hơn iOS 6.0 hoặc Mac OS X 10.8

Bạn cần sử dụng dispatch_retaindispatch_releasetrong hàng đợi của bạn. ARC không quản lý chúng.

Nếu mục tiêu triển khai của bạn là iOS 6.0 hoặc Mac OS X 10.8 trở lên

ARC sẽ quản lý hàng đợi của bạn cho bạn. Bạn không cần (và không thể) sử dụng dispatch_retainhoặc dispatch_releasenếu ARC được bật.

Chi tiết

Bắt đầu từ SDK iOS 6.0 và Mac OS X 10.8 SDK, mọi đối tượng điều phối (bao gồm cả a dispatch_queue_t) cũng là một đối tượng Objective-C. Điều này được ghi lại trong <os/object.h>tệp tiêu đề:

 * By default, libSystem objects such as GCD and XPC objects are declared as
 * Objective-C types when building with an Objective-C compiler. This allows
 * them to participate in ARC, in RR management by the Blocks runtime and in
 * leaks checking by the static analyzer, and enables them to be added to Cocoa
 * collections.
 *
 * NOTE: this requires explicit cancellation of dispatch sources and xpc
 *       connections whose handler blocks capture the source/connection object,
 *       resp. ensuring that such captures do not form retain cycles (e.g. by
 *       declaring the source as __weak).
 *
 * To opt-out of this default behavior, add -DOS_OBJECT_USE_OBJC=0 to your
 * compiler flags.
 *
 * This mode requires a platform with the modern Objective-C runtime, the
 * Objective-C GC compiler option to be disabled, and at least a Mac OS X 10.8
 * or iOS 6.0 deployment target.

Điều này có nghĩa bạn có thể lưu trữ hàng đợi của bạn trong một NSArrayhoặc NSDictionary, hoặc trong một tài sản với một trong những strong, weak, unsafe_unretained, assign, hoặc retaincác thuộc tính. Điều đó cũng có nghĩa là nếu bạn tham chiếu đến hàng đợi của mình từ một khối, khối đó sẽ tự động giữ lại hàng đợi.

Vì vậy, nếu mục tiêu triển khai của bạn ít nhất là iOS 6.0 hoặc Mac OS X 10.8 và bạn đã bật ARC, ARC sẽ giữ lại và giải phóng hàng đợi của bạn, đồng thời trình biên dịch sẽ gắn cờ bất kỳ nỗ lực nào để sử dụng dispatch_retainhoặc dispatch_releaselà lỗi.

Nếu mục tiêu triển khai của bạn ít nhất là iOS 6.0 hoặc Mac OS X 10.8, và bạn có ARC tàn tật , bạn phải tự duy trì và giải phóng hàng đợi của bạn, hoặc bằng cách gọi dispatch_retaindispatch_release, hoặc bằng cách gửi hàng đợi retainreleasetin nhắn (như [queue retain][queue release]).

Để tương thích với các cơ sở mã cũ, bạn có thể ngăn trình biên dịch xem hàng đợi của bạn như một đối tượng Objective-C bằng cách xác định OS_OBJECT_USE_OBJCthành 0. Ví dụ: bạn có thể đặt điều này vào .pchtệp của mình (trước bất kỳ #importcâu lệnh nào ):

#define OS_OBJECT_USE_OBJC 0

hoặc bạn có thể thêm OS_OBJECT_USE_OBJC=0làm macro bộ xử lý trước trong cài đặt bản dựng của mình. Nếu bạn đặt OS_OBJECT_USE_OBJCthành 0, ARC sẽ không giữ lại hoặc giải phóng hàng đợi của bạn cho bạn và bạn sẽ phải tự thực hiện bằng cách sử dụng dispatch_retaindispatch_release.


1
Tuy nhiên, lưu ý rằng thay đổi mới chỉ định các đối tượng điều phối là các đối tượng Objective-C. Do đó, ngay cả khi ARC bị vô hiệu hóa, các đối tượng này sẽ tự động được giữ lại nếu được một khối bắt giữ - giống như tất cả các đối tượng Objective-C khác.
Jody Hagins

3
Có một trường hợp cạnh thú vị. Nếu thư viện của bạn triển khai lên iOS 5.1 và ứng dụng của bạn lên 6.0 và bạn đang sử dụng ARC, bạn cần dispatch_release NULL đối tượng trong deallocmã 5.1 của mình . Nếu không, một cái gì đó (mã do trình biên dịch tạo ra? Bản thân thời gian chạy?) Sẽ cố gắng giải phóng đối tượng lần thứ hai.
Steven Fisher,

Tôi có cần gửi các đối tượng nguồn khác mà tôi tạo khi sử dụng Mac OS 10.7 không?
p0lAris

Bạn phải giữ lại / giải phóng thủ công tất cả các đối tượng GCD trong OS X 10.7.
cướp mayoff

23

Chỉ cần theo dõi ở đây ... Nếu mục tiêu triển khai tối thiểu của bạn là iOS 6, ARC hiện quản lý chúng.


Điều này cũng áp dụng cho Sư tử núi. Nếu mục tiêu triển khai của bạn là iOS 6 hoặc Mountain Lion, bạn không thể (theo mặc định) sử dụng disp_release vì đó là macro gửi thông báo phát hành đến đối tượng không được phép theo ARC.
Emil Eriksson
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.