11

Tôi hiểu rằng bạn cần phải cẩn thận với autorelease trên iOS. Tôi có một phương thức trả về một đối tượng là alloc s mà người gọi cần, vì vậy trong tình huống này - như tôi đã hiểu - tôi cần gửi autorelease cho đối tượng trong callee trước khi nó trả về.Khi nào autorelease thực sự gây ra một bản phát hành trong Cocoa Touch?

Điều này là tốt, nhưng khi điều khiển trở lại điện thoại (tức là sau khi lần nhấp nút của tôi đã được xử lý) có vẻ như là nhóm tự động phát hành được giải phóng. Tôi nghi ngờ đây là cách nó được cho là, nhưng tôi tự hỏi thực hành tốt nhất cho tình huống này là gì.

Tôi đã sử dụng để gửi tin nhắn retain từ người gọi để đối tượng không được nhả và sau đó phát hành rõ ràng trong dealloc.

Đây có phải là cách tiếp cận tốt nhất không?

Trả lời

21

Bể tự động phát hành thường được phát hành sau mỗi lần lặp của vòng lặp chạy. Nói chung, mọi ứng dụng Cocoa và Cocoa Touch đều có cấu trúc như sau:

Get the next message out of the queue 
Create an autorelease pool 
Dispatch the message (this is where your application does its work) 
Drain the autorelease pool 

Những gì bạn mô tả là hành vi mong đợi. Nếu bạn muốn giữ một đối tượng xung quanh lâu hơn thế, bạn sẽ cần phải giữ lại nó một cách rõ ràng.

2

Vâng, đó là cách tiếp cận tốt nhất. Tự động thực sự chỉ dành cho các tương tác trong mã mà bạn biết. Khi bạn đang lưu trữ một đối tượng, bạn nên biết rằng đối tượng chứa một tham chiếu sẽ không chết/thoát khỏi phạm vi cho đến khi bạn cũng được thực hiện với đối tượng, hoặc bạn cần giữ lại đối tượng.

1

Nó chỉ đảm bảo rằng các đối tượng tự động phát hành sẽ được phát hành sau khi kết thúc phương pháp của bạn. Sau khi tất cả, phương pháp được gọi là phương pháp của bạn có thể đã tạo ra hồ bơi riêng của mình và phát hành nó ngay sau khi phương pháp của bạn.

+0

Nói đúng ra, thậm chí là không được bảo đảm, vì bạn có thể tạo ra một hồ bơi trong một phương pháp, autorelease một số đối tượng, và lấy nước từ các hồ bơi trong phương pháp khác. Một thiết kế không rõ ràng, nhưng hợp lệ: Các đối tượng sẽ kéo dài tất cả các cách từ việc tạo ra hồ bơi đến hệ thống thoát nước của hồ bơi, bất kể phương thức tạo hồ bơi trở lại. –

13

Sử dụng autorelease là cách nói, "Đối tượng, tôi không muốn bạn nữa, nhưng tôi sẽ chuyển bạn cho người khác có thể muốn bạn, vì vậy đừng biến mất." Vì vậy, đối tượng sẽ dính xung quanh đủ lâu để bạn trả lại từ một phương pháp hoặc đưa nó cho một đối tượng khác. Khi một số mã muốn giữ đối tượng xung quanh, nó phải yêu cầu quyền sở hữu bằng cách retain nhập nó.

Xem the memory management guidelines để biết mọi thứ bạn cần biết để sử dụng chính xác autorelease.

+0

Câu trả lời hay NHƯNG __đây là an toàn__? Có một ví dụ về thời gian khi bạn trả về một đối tượng mà bạn '[[[đối tượng cấp phát] init] autorelease]', nhưng sau đó đối tượng biến mất trước khi bạn có cơ hội sử dụng nó? – bobobobo

+0

@bobobobo: Không phải nếu bạn tuân thủ các quy tắc quản lý bộ nhớ. Hành vi của 'autorelease' là khá có thể dự đoán được - đối tượng sẽ ở lại xung quanh cho đến khi vùng tự động thoát hiện tại được thoát ra, điều này sẽ không xảy ra cho đến khi kết thúc vòng lặp sự kiện hiện tại (trừ khi bạn cố tình làm cho nó xảy ra sớm hơn).Nếu bạn nói, trỏ một biến mẫu tới đối tượng nhưng không giữ lại nó và sau đó thử truy cập nó sau này, đối tượng sẽ biến mất trước khi bạn có cơ hội sử dụng nó - nhưng đó là vì bạn đã phá vỡ quản lý bộ nhớ hợp đồng khi bạn không giữ lại đối tượng. – Chuck

3

Dưới đây là một examle cung cấp trong the Apple Memory Management document:

– (id)findMatchingObject:(id)anObject 
{ 
    id match = nil; 
    while (match == nil) { 
     NSAutoreleasePool *subPool = [[NSAutoreleasePool alloc] init]; 
     /* Do a search that creates a lot of temporary objects. */ 
     match = [self expensiveSearchForObject:anObject]; 
     if (match != nil) { 
      [match retain]; /* Keep match around. */ 
     } 
     [subPool release]; 
    } 
    return [match autorelease]; /* Let match go and return it. */ 
} 
Các vấn đề liên quan