Khi nào tôi nên giải phóng các đối tượng trong - (void) viewDidUnload thay vì trong -dealloc?


Câu trả lời:


51

Ngoài những gì đã được chỉ ra, tôi muốn giải thích thêm về logic đằng sau -viewDidUnload.

Một trong những lý do quan trọng nhất để triển khai nó là các UIViewControllerlớp con thường cũng chứa các tham chiếu sở hữu đến các chế độ xem con khác nhau trong hệ thống phân cấp chế độ xem. Những thuộc tính này có thể đã được thiết lập thông qua IBOutletskhi tải từ một nib, hoặc được lập trình bên trong -loadViewchẳng hạn.

Quyền sở hữu bổ sung của UIViewControllercác chế độ xem phụ có nghĩa là ngay cả khi chế độ xem của nó bị xóa khỏi hệ thống phân cấp chế độ xem và được giải phóng để tiết kiệm bộ nhớ, qua đó các chế độ xem phụ cũng được chế độ xem giải phóng, chúng sẽ không thực sự bị phân bổ vì UIViewControllerbản thân nó vẫn chứa điểm nổi bật của riêng nó giữ lại các tham chiếu đến các đối tượng đó. Giải phóng UIViewControllerquyền sở hữu bổ sung của các đối tượng này đảm bảo chúng cũng sẽ được phân bổ để giải phóng bộ nhớ.

Các đối tượng mà bạn phát hành ở đây thường được tạo lại và thiết lập lại khi UIViewControllerchế độ xem ở đó re-loaded, từ Nib hoặc thông qua triển khai -loadView.

Cũng lưu ý rằng thuộc UIViewController viewtính niltại thời điểm phương thức này được gọi.


1
Bạn nên đọc developer.apple.com/library/ios/#featuredarticles/… để hiểu vòng đời của bộ điều khiển chế độ xem / xem
Paul Solt

21

Như tài liệu cho biết :

Nó được gọi trong điều kiện bộ nhớ thấp khi bộ điều khiển chế độ xem cần giải phóng chế độ xem của nó và bất kỳ đối tượng nào được liên kết với chế độ xem đó để giải phóng bộ nhớ.

Trong tình cảnh tương tự deallockhông gọi. Phương pháp này chỉ khả dụng trong OS3 trở lên. Đối phó với tình huống tương tự trong iPhone OS 2.x là một nỗi đau thực sự!

Cập nhật tháng 7 năm 2015 : Cần lưu ý rằng nó viewDidUnloadđã không được chấp nhận trong iOS 6 vì "Chế độ xem không còn bị xóa trong điều kiện bộ nhớ thấp và vì vậy phương pháp này không bao giờ được gọi." Vì vậy, lời khuyên hiện đại là đừng lo lắng về nó và sử dụng dealloc.


6
Cũng từ tài liệu: "Bạn chỉ nên thực hiện việc này đối với các đối tượng mà bạn có thể dễ dàng tạo lại sau này, trong phương thức viewDidLoad hoặc từ các phần khác của ứng dụng. Bạn không nên sử dụng phương pháp này để giải phóng dữ liệu người dùng hoặc bất kỳ thông tin nào khác không thể dễ dàng tái tạo ”. Đó là một câu hỏi mà tôi cũng đã có, cảm ơn!
leolobato 21/07/09

Nếu chế độ xem hiện đang hiển thị thì sao? Sẽ không tệ nếu đánh rơi nó vì cảnh báo bộ nhớ thấp? ;) thì ứng dụng sẽ trống rỗng. Tôi không hiểu quan điểm của việc giải phóng chế độ xem vì bộ nhớ thấp. Nếu tôi không thấy một khung nhìn, tôi luôn nhả toàn bộ bộ điều khiển. Althogh Tôi có một bộ điều khiển xem gốc mà vẫn còn nguyên vẹn và quản lý tất cả các tải / dỡ của nó nhìn con điều khiển ...
Cảm ơn

Không, bạn sẽ không sử dụng cái này nếu bạn chỉ hoán đổi một chế độ xem này cho một chế độ xem khác. Hãy nghĩ đến trường hợp bạn có một "chồng" chế độ xem với UINavigationController. Chỉ một chế độ xem được hiển thị và nếu bạn có cảnh báo bộ nhớ, bạn có thể giải phóng tất cả những chế độ không hiển thị.
Stephen Darlington

Làm thế nào để bạn kiểm soát rằng viewDidUnload không được gọi trên chế độ xem hiển thị hiện tại như Cảm ơn đã lưu ý?
arielcamus

1
viewDidUnload sẽ không được gọi trên chế độ xem hiện đang hiển thị, chỉ trên các chế độ xem không hiển thị.
progrmr

9

Điều này là do bạn thường sẽ đặt @propertynhư "(nonatomic, retain)"và như vậy, bộ cài đặt được tạo cho bạn giải phóng đối tượng hiện tại và sau đó giữ lại đối số tức là

self.property = nil;

... làm điều gì đó dọc theo dòng:

[property release];
property = [nil retain];

Do đó, bạn đang giết hai con chim bằng một viên đá: quản lý bộ nhớ (giải phóng đối tượng hiện có) và gán con trỏ là nil (vì gửi bất kỳ thông báo nào đến con trỏ nil sẽ trả về nil).

Hy vọng rằng sẽ giúp.


8

Hãy nhớ rằng đó viewDidUnloadlà một phương thức trong bộ điều khiển chế độ xem, không phải trong chế độ xem. Các nhân xem dealloc phương pháp sẽ được gọi khi unloads xem, nhưng của view controller dealloc phương pháp có thể không được gọi cho đến sau này.

Nếu bạn nhận được cảnh báo bộ nhớ thấp và chế độ xem của bạn không hiển thị, điều này sẽ xảy ra vào bất kỳ lúc nào bạn sử dụng UIImagePickerController để cho phép người dùng chụp ảnh, chế độ xem của bạn sẽ bị dỡ bỏ và sẽ cần tải lại sau đó.


điều đó có ý nghĩa. Điều gì xảy ra nếu tôi luôn thả toàn bộ bộ điều khiển chế độ xem? Đó là những gì tôi thực sự làm. Trong trường hợp này, tôi không phải xử lý nhiều với -viewDidUnload, phải không? Tôi chưa bao giờ gặp trường hợp chỉ thả chế độ xem, vì tôi luôn thả toàn bộ bộ điều khiển nếu nó không hiển thị.
Cảm ơn

tốt, chỉ cần nhớ rằng trong trường hợp chế độ xem của bạn đang hiển thị, nhưng bạn có chế độ xem toàn màn hình như ImagePicker ở phía trên, chế độ xem của bạn có thể bị dỡ bỏ ngay cả khi bạn không có kế hoạch.
David Maymudes

6

Phần kết luận:

View Controllers có thuộc tính view. Thông thường, một ngòi hoặc đoạn mã sẽ thêm các chế độ xem khác vào chế độ xem này. Điều này thường xảy ra bên trong phương thức -viewDidLoad, như thế này:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self createManyViewsAndAddThemToSelfDotView];
}

Ngoài ra, một tệp nib có thể tạo một nút và nối nó vào chế độ xem của bộ điều khiển chế độ xem.

Trên iPhone OS 2.2, khi -didReceiveMemoryWarning được gọi từ hệ thống, bạn phải giải phóng thứ gì đó để giải phóng bộ nhớ. Bạn có thể giải phóng toàn bộ khung nhìn của bộ điều khiển chế độ xem nếu điều đó hợp lý. Hoặc chỉ những nội dung tiêu tốn bộ nhớ lớn trong đó.

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

Bây giờ, trong OS 3.0 mới, có một phương thức -viewDidUnload, phương thức này sẽ được gọi từ hệ thống khi chế độ xem đã được tải xuống do bộ nhớ thấp (vui lòng sửa cho tôi: chính xác thì phương thức này được gọi là khi nào?)

-viewDidUnload được sử dụng để giải phóng tất cả các đối tượng thuộc sở hữu của chính bộ điều khiển chế độ xem và chế độ xem. Lý do: Nếu một bộ điều khiển chế độ xem giữ các tham chiếu đến các chế độ xem con của chế độ xem, tức là một nút, các chế độ xem con được tham chiếu sẽ không được giải phóng, vì số lượng giữ lại của chúng là> = 1. Sau khi chúng được giải phóng trong -viewDidUnload, chúng có thể được giải phóng từ ký ức.


1
Nhớ lại trong chế độ xem đã dỡ xuống để làm self.button = nil ;, not [button nhả] ;.
mk 12

6

Apple không dùng viewWillUnload nữa, bây giờ bạn nên sử dụng didReceiveMemoryWarning hoặc dealloc để phát hành các tài liệu phản đối của mình.

Trong iOS 6, các phương thức viewWillUnload và viewDidUnload của UIViewController hiện không được dùng nữa. Nếu bạn đang sử dụng các phương pháp này để giải phóng dữ liệu, hãy sử dụng phương thức didReceiveMemoryWarning. Bạn cũng có thể sử dụng phương pháp này để giải phóng các tham chiếu đến chế độ xem của bộ điều khiển chế độ xem nếu nó không được sử dụng. Bạn sẽ cần kiểm tra xem chế độ xem không nằm trong cửa sổ trước khi thực hiện việc này.


5

Nếu bộ điều khiển chế độ xem được bật ra từ ngăn xếp bộ điều khiển điều hướng và không được giữ lại ở bất kỳ nơi nào khác, nó sẽ được phân bổ và dealloc sẽ được gọi thay vì viewDidUnload. Bạn nên giải phóng các khung nhìn được tạo trong loadView trong dealloc, nhưng không cần thiết phải đặt các biến thành nil, vì ngay sau khi dealloc được gọi, các biến sẽ không còn tồn tại nữa.


3

Bạn có thể phát hành bất kỳ lượt xem phụ nào mà bạn giữ lại, chẳng hạn như UIImageView mà bạn đã giữ lại trong phương thức loadView của mình hoặc tốt hơn là hình ảnh trên UIImageView đó.

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.