2009-03-05 24 views
14

Tôi đang tìm một nguồn chính (hoặc lời giải thích thực sự tốt) để sao lưu khiếu nại rằng việc sử dụng autorelease là nguy hiểm hoặc quá đắt khi viết phần mềm cho iPhone.Tại sao tính năng tự động phát lại đặc biệt nguy hiểm/tốn kém cho các ứng dụng iPhone?

Một số nhà phát triển đưa ra xác nhận quyền sở hữu này và tôi thậm chí còn nghe nói rằng Apple không khuyến nghị, nhưng tôi không thể bật bất kỳ nguồn cụ thể nào để sao lưu.

tài liệu tham khảo SO:
autorelease-iphone
Why does this create a memory leak (iPhone)?

Lưu ý: Tôi có thể thấy, từ một quan điểm về khái niệm của xem, mà autorelease là hơi đắt hơn một cuộc gọi đơn giản để release, nhưng tôi không nghĩ rằng hình phạt nhỏ là đủ để làm cho Apple khuyên bạn nên chống lại nó.

Câu chuyện có thật là gì?

Trả lời

11

(? Không thể chấp nhận câu trả lời của riêng bạn)

Vâng, sau khi tất cả những gì, tôi đã quản lý để tìm thấy một tài liệu tham khảo từ Apple phát triển, thêm vào như là một phụ lưu ý gần cuối trang:

iPhone OS Lưu ý: Bởi vì trên iPhone OS một ứng dụng thực thi trong một môi trường bộ nhớ hạn chế hơn, việc sử dụng bể autorelease được nản chí trong các phương pháp hoặc các khối mã (ví dụ, vòng), nơi một crea ứng dụng nhiều đối tượng. Thay vào đó, bạn nên giải phóng rõ ràng các đối tượng bất cứ khi nào có thể.

Tuy nhiên, điều này cho thấy việc sử dụng tự động cẩn thận, không tránh hoàn toàn.

(và bây giờ cho nhận xét của tôi)

Có vẻ như có một số tiền nhất định trong việc duy trì hồ bơi. Tôi đọc số this article, điều này sẽ khiến tôi có thể tránh tự động phát càng nhiều càng tốt vì tôi thích mọi thứ nhất quán. Nếu bạn có một số bộ nhớ dưới autorelease và bộ nhớ khác được quản lý hoàn toàn bằng tay nó có thể là một chút khó hiểu hơn.

+0

vui lòng giúp đỡ (đã cho tôi điều gì đó để tìm kiếm :-) – TofuBeer

+1

Những gì họ không đề cập đến là rất nhiều lớp trong Tự động gọi là Foundation trên các đối tượng mà họ quản lý và do đó trong các vòng chặt chẽ bạn cần tạo và quản lý các nhóm tự động phát hành riêng nếu bạn đang xử lý ngay cả một lượng dữ liệu khiêm tốn. – rpetrich

+1

Tôi không nghĩ rằng đó là chi phí trong việc duy trì hồ bơi; thay vào đó, tốt nhất là không nên cấp phát bộ nhớ nhưng không được sử dụng lâu hơn mức cần thiết trong môi trường hạn chế bộ nhớ. Tự động trả lại bộ nhớ được cấp phát dài hơn mức cần thiết. – Paul

0

Tôi rất muốn đề nghị tránh tự động phát hiện như bệnh dịch hạch. Lỗi quản lý bộ nhớ là cách tuyệt vời để lãng phí một lượng lớn thời gian và tiền bạc, tôi đã có vinh dự đáng ngờ khi trải qua quá trình nhiều lần trên các ứng dụng Mac cũ và thực tế là iPhone có những hạn chế về bộ nhớ chặt chẽ có nghĩa là bạn có phải cực kỳ cẩn thận hoặc ứng dụng sẽ không ổn định và thường xuyên gặp sự cố ... giống như nhiều ứng dụng đầu tiên được phát hành vào mùa hè năm ngoái.

Cách đáng tin cậy duy nhất tôi tìm thấy để viết các ứng dụng iPhone ổn định là tự quản lý tất cả bộ nhớ của bạn và thực hiện nó một cách nhất quán. Ngay cả khi bạn là lập trình viên duy nhất trong dự án của bạn, bạn sẽ cảm ơn bản thân sau này. Nó có thể khó khăn nếu bạn học lập trình bằng ngôn ngữ "chăm sóc mọi thứ cho bạn", nhưng thực sự đáng học cách làm tốt nếu bạn nghiêm túc về việc tạo ra các ứng dụng iPhone chất lượng.

+9

-1. Bạn chắc chắn có thể nói nó hơi kém hiệu quả, nhưng autorelease không tạo ra lỗi. Nếu bạn làm theo các quy tắc quản lý bộ nhớ (bao gồm cả tự động phát hành), bạn sẽ không có lỗi bộ nhớ. Nếu bạn không tuân thủ các quy tắc, việc giải phóng thủ công mọi thứ sẽ không giúp bạn tiết kiệm. – Chuck

5

Tôi không đồng ý rằng tránh tự động hoàn toàn là khôn ngoan.

Cocoa Touch sử dụng nó khá thường xuyên trong nội bộ và trong nhiều trường hợp, đó là cách duy nhất để cấp phát bộ nhớ đúng cách (ví dụ điển hình là các ô xem bảng có thể tái sử dụng). Nếu bạn hiểu những gì đang xảy ra, các hồ bơi autorelease là một công cụ tuyệt vời theo ý của bạn. Điều chính cần nhớ là các khối không được giải phóng cho đến khi một số điểm sau đó trong vòng lặp chạy. Nếu bạn đang chạy một vòng lặp chặt chẽ mà không có sự tương tác của người dùng và đang xếp chồng các khối tự động phát, cuối cùng bạn sẽ hết bộ nhớ.

Tự động trả tiền không thay thế cho thu gom rác (không có sẵn trong SDK iPhone) và có thể dẫn đến lỗi con trỏ nguy hiểm (con trỏ vẫn có vẻ tốt, sau đó tại một số điểm không thể đoán trước sẽ không hợp lệ), nhưng cũng rất hữu ích trong việc viết rõ ràng và dễ bảo trì mã. Hãy xem xét trường hợp sau:

[aDictionary writeToFile: 
    [documentsDirectory stringByAppendingPathComponent:@"settings.plist"] 
       atomically:YES]; 

Chuỗi đường dẫn được tạo dưới dạng đối tượng tự động. Chúng tôi không bắt buộc phải tạo một đối tượng tạm thời, vì vậy chúng tôi tránh được chi phí đó (và khả năng chúng tôi có thể quên phát hành nó). Bộ nhớ sẽ được phát hành hoàn toàn (không bị rò rỉ), chỉ là nó sẽ xảy ra sau đó trong vòng lặp chạy. Hãy tự hỏi mình: liệu tôi sẽ phân bổ hàng trăm cái này trước khi tôi quay lại đầu vào của người dùng? Nếu không (như trường hợp ở đây), autorelease là một giải pháp tuyệt vời và thực sự phương pháp NSString này để làm việc với các đường dẫn chỉ có sẵn bằng cách sử dụng bộ nhớ tự động phát hành.

Tôi đồng ý với áp phích ở trên mà theo quy ước và nhất quán là một ý tưởng rất hay.

4

Tôi có xu hướng tránh sử dụng autorelease trên iPhone nơi tôi có thể (như Jon chỉ ra, bạn không thể luôn luôn làm nếu không có nó), đơn giản bởi vì tôi muốn biết rằng các đối tượng tôi đang làm việc được phát hành ngay lập tức Tôi không cần chúng. Hạn chế về bộ nhớ là một trong những vấn đề lớn nhất mà bạn sẽ gặp phải trên thiết bị và tôi tin rằng đó là nguồn gốc của hầu hết các sự cố gặp sự cố bạn sẽ tìm thấy ở đó.

Như được đánh dấu bởi Apple, một lĩnh vực quan tâm cụ thể là khi bạn sử dụng các đối tượng được tự động phát hành trong bất kỳ loại vòng lặp nào, vì chúng sẽ chồng chất trong hồ bơi tự động. Sau đó, bạn phải quản lý khi nào thoát khỏi hồ bơi hoặc tạo/giải phóng một hồ bơi. Làm điều đó mỗi lần đi qua vòng lặp có thể làm giảm hiệu suất, nhưng đi quá nhiều lần mà không có thể dẫn đến việc sử dụng bộ nhớ nguy hiểm. Tôi vẫn đang điều chỉnh điều này trong Molecules, bởi vì có những vấn đề bộ nhớ liên tục khi nhập các tệp văn bản lớn (> 2 MB) từ Ngân hàng Dữ liệu Protein. Tôi đã có thể cải thiện hiệu suất bằng cách giảm thiểu các đối tượng tự động phát hành, nhưng không thể loại bỏ chúng hoàn toàn.

Khu vực khác cần lưu ý là đang sử dụng các đối tượng được tự động phát hành có chuỗi. Nếu có thể, không sử dụng các đối tượng được tự động phát hiện khi xử lý các phương thức được thực hiện trên một luồng nền, vì hồ bơi có thể được rút ra vào các thời điểm ngẫu nhiên. Điều này dẫn đến các sự cố gián đoạn có thể thực sự thú vị khi theo dõi.

9

Nó không phải là câu hỏi để sử dụng hoặc không sử dụng tự động phát hành, bởi vì trong một số trường hợp autorelease là cách duy nhất bạn sẽ vượt qua. Câu hỏi phải là "Tại sao không sử dụng tự động phát trên tất cả các đối tượng, thay vì sử dụng giữ lại và giải phóng?".

Để trả lời điều đó, trước hết bạn nên tìm hiểu cách sử dụng thích hợp cho tự động phát hành. Giả sử bạn có một lớp có hai thuộc tính: firstName và lastName. Có một getter và một setter cho mỗi. Nhưng bạn cũng cần một phương thức có thể trả về fullName, bằng cách ghép hai chuỗi này thành một chuỗi hoàn toàn mới:

- (NSString *) fullName { 
    NSString str = [[NSString alloc]initWithFormat:@"%@ %@", firstName, lastName]; 
    // this is not good until we put [str autorelease]; 
    return str; 
} 

Có gì sai với ảnh đó? Số lượng tham chiếu trên chuỗi được trả về là 1, vì vậy nếu bạn không muốn bị rò rỉ, người gọi sẽ phát hành nó khi hoàn thành.Từ quan điểm của người gọi, anh ta chỉ yêu cầu một giá trị tài sản fullName. Anh không biết thực tế là anh có một vật thể hoàn toàn mới mà anh nên phát hành sau khi sử dụng, và không phải là một số tham chiếu đến một NSString trong nội bộ được tổ chức bởi lớp học!

Nếu chúng tôi đặt [str release] trước khi trở về, chuỗi sẽ bị hủy và phương thức sẽ trả về rác! Đó là nơi chúng tôi sử dụng [str autorelease], để đánh dấu đối tượng để phát hành sau này (thường là khi xử lý sự kiện được thực hiện). Bằng cách đó người gọi nhận được đồ vật của mình, và không phải lo lắng liệu anh ta có nên thả nó hay không.

Quy ước là gọi tự động phát lại trên đối tượng mới trước khi phương thức trả lại cho người gọi. Ngoại lệ là các phương thức có tên bắt đầu bằng alloc, new hoặc copy. Trong những trường hợp như vậy, người gọi biết rằng một đối tượng hoàn toàn mới được tạo ra cho họ và đó là nhiệm vụ của họ để gọi phát hành trên đối tượng đó.

Thay thế phát hành với tự động hoàn toàn là một ý tưởng tồi, vì các đối tượng sẽ chồng chất và làm tắc nghẽn bộ nhớ rất nhanh, đặc biệt là trong các vòng lặp. Các tài nguyên trên iPhone bị hạn chế, do đó, để giảm thiểu việc hoán đổi bộ nhớ, đó là nhiệm vụ của bạn để giải phóng đối tượng ngay khi bạn hoàn thành nó.

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