2012-11-27 20 views
34

Ai đó có thể giải thích cho tôi mục đích có __autoreleasing trong khối mã mẫu sau đây không?NSError và __autoreleasing

- (void)execute:(NSError * __autoreleasing *)error { 
    // do stuff, possibly assigning error if something went wrong 
} 

Tôi đã xóa __autoreleasing và mọi thứ vẫn có vẻ biên dịch/chạy tốt. Tôi bắt đầu sử dụng bài đăng obj-c ARC vì vậy tôi chưa bao giờ thực sự học/hiểu tất cả những điều đó. Tôi đã đọc các ARC transition guide, nhưng tôi không hoàn toàn hiểu ví dụ NSError của họ.

Trả lời

63

xem xét như thế nào ARC làm việc với biến - mỗi biến tài liệu tham khảo có một chế độ (ngầm hoặc rõ ràng): mạnh, yếu vv Chế độ này cho phép của ARC biết làm thế nào để xử lý đọc và viết để biến; ví dụ. cho việc đọc biến số mạnh mẽ không yêu cầu thêm hành động nào trong khi viết yêu cầu giải phóng tham chiếu hiện tại trong biến trước khi thay thế bằng biến mới. ARC cần biết chế độ của bất kỳ biến nào để hoạt động.

Bây giờ, hãy xem xét các biến tự được chuyển bởi tham chiếu, ví dụ: cho bạn execute bạn sẽ có một cuộc gọi dọc theo dòng:

NSError *myError = nil; 
... 
[someObject execute:&myError]; // pass the variable itself by reference, not the variables value 

và cơ thể của execute sẽ chứa một bài tập dọc theo dòng:

- (void)execute:(NSError * __autoreleasing *)error 
{ 
    ... 
    if (error != NULL) 
     *error = [NSError ...]; // assign indirectly via the reference to a variable 
    ... 
} 

Bây giờ cho rằng nhiệm vụ gián tiếp ARC cần biết chế độ của biến được tham chiếu để nó biết cách đọc và viết. Đó là những gì các __autoreleasing là trong tuyên bố, nó nói với ARC rằng nó đã được thông qua một tham chiếu đến một biến có chế độ là autoreleasing và điều đó cho ARC biết cách đọc và ghi nội dung của biến. Loại bỏ các __autoreleasing và một chế độ mặc định sẽ được giả định, và trong trường hợp này tôi muốn đề nghị rõ ràng là chắc chắn tốt.

Chế độ tự động tự động trả tiền có nghĩa là biến chứa tham chiếu không thuộc sở hữu, lần đọc giữ lại nếu cần và viết chỉ có thể viết. Nó được sử dụng chủ yếu cho các biến được truyền qua tham chiếu.

Bạn có thể nhận thấy rằng trong ví dụ trên biến myError có chế độ mạnh (ngầm) nhưng nó được thông qua tham khảo như autoreleasing - trình biên dịch xử lý này sẽ tự động bằng cách giới thiệu một biến autoreleasing tạm thời, sao chép không giữ lại tham chiếu hiện tại trong myError vào đó và chuyển tạm thời theo tham chiếu làm đối số đến execute:. Sau khi cuộc gọi trả về trình biên dịch thực hiện một nhiệm vụ bình thường từ tạm thời đến myError, kết quả trong bất kỳ tài liệu tham khảo cũ được phát hành và một trong những trả lại giữ lại.

Để biết thêm chi tiết, xem Apple's Transitioning to ARC Release Notes

followup để Comments

Q: Liệu __autoreleasing ngầm thiết lập?

A: Vâng Apple's tài liệu không cụ thể, nhưng Clang documentation nói rằng nó là ẩn đối với các tham số gián tiếp. Như trên, tôi khuyên bạn nên rõ ràng, rõ ràng là một Good Thing ™.

Q: Vị trí có quan trọng không?

A: Có, và không ... Đây là bản khai C, nội dung câu đố ("Tuyên bố sau đây ...") là gì. Vòng loại phải nằm giữa hai dấu hoa thị vì nó là con trỏ tự động đến con trỏ tự động (biến kiểu) đối với một đối tượng, nhưng Apple trình biên dịch là "tha thứ" mà không được cụ thể về những gì nó tha thứ. Chơi nó an toàn, đặt nó vào đúng nơi.

Q: Nếu bạn không kiểm tra errorNULL trước khi thực hiện chuyển nhượng gián tiếp?

A: Tất nhiên, bạn nên ở đâu đó trước khi bạn thực hiện việc chuyển hướng. Mã được hiển thị chỉ là một đường viền và các chi tiết như vậy được elided và bao phủ bởi các của .... Tuy nhiên vì nó đã được nâng lên một vài lần trong những năm qua có lẽ tôi đã bỏ qua quá nhiều, một số if phù hợp đã được thêm vào.

+0

Vì vậy, '__autoreleasing' được đặt ngầm định nếu tôi không đặt rõ ràng? Ngoài ra, vị trí của vấn đề '__autoreleasing' (trước, bên trong hoặc sau dấu sao)? – chinabuffet

+0

@chinabuffet - Xem followup trong câu trả lời – CRD

+1

@CRD câu trả lời hay. Nhưng bạn có thể muốn chỉ ra rằng bạn nên kiểm tra nếu 'error' là' NULL' trước khi gán cho '* error'. Nếu không, phương pháp của bạn có thể làm hỏng ứng dụng của bạn vì '[foo execute: NULL]' là một thực thi hoàn toàn hợp lệ và cách để nói "Tôi không quan tâm đến lỗi". – Joel

Các vấn đề liên quan