2009-01-29 43 views
5

Bối cảnh:Phát triển iPhone - Mô phỏng Cảnh báo bộ nhớ

Tôi có ứng dụng thanh tab. Mỗi tab chứa trình điều khiển điều hướng cho phép người dùng chuyển từ chế độ xem này sang chế độ xem khác hiển thị thông tin chi tiết về dữ liệu (mỗi chế độ xem đang được xử lý bởi bộ điều khiển chế độ xem và mỗi loại bộ điều khiển chế độ xem có phương thức didReceiveMemoryWarning). Danh sách được điền bằng cách kéo dữ liệu từ các dịch vụ web.

Vấn đề:

Khi tôi sử dụng "Phần cứng> Mô phỏng Memory Cảnh báo" tùy chọn của iPhone Simulator, phương pháp didReceiveMemoryWarning được gọi cho tất cả các bộ điều khiển quan điểm của tôi - ngay cả những ai mà người dùng đang xem. Tôi không muốn xóa bất kỳ nội dung nào đang được sử dụng bởi bộ điều khiển chế độ xem đang kích hoạt. Làm thế nào tôi có thể đạt được điều đó?

Phương pháp nào cần phải triển khai để tải lại dữ liệu sau khi dữ liệu được phát hành do cảnh báo bộ nhớ? (Tôi thấy rằng các lớp học xem điều khiển có chứa một cuộc gọi xem bảng viewDidLoad phương pháp khi người dùng quay trở lại với quan điểm đó, nhưng nếu xem có chứa (nói UIWebView) sau đó viewDidLoad phương pháp không được gọi. Tại sao vậy?)

thay đổi nội dung (Thứ Sáu ngày 30 Tháng 1 năm 2009 - 03:10)

(Lưu ý:. tôi đang sử dụng xây dựng giao diện cho việc tạo quan điểm, và loadView phương pháp là nhận xét ra)

vì vậy, khi một bộ điều khiển xem nhận thông báo cảnh báo bộ nhớ, đây là các bước được thực hiện:

  1. phương pháp sau được gọi là:

    - (void)didReceiveMemoryWarning { 
        [super didReceiveMemoryWarning]; 
    } 
    
  2. Theo kết quả của cuộc gọi đến [super didReceiveMemoryWarning], [self setView:nil] được tự động gọi?

  3. Nếu bất kỳ tài nguyên nào cần được xóa thì phương pháp setView phải được ghi đè để xóa tài nguyên cục bộ.

  4. [self setView:nil] không được gọi nếu chế độ xem hiện đang hoạt động (Theo mặc định). Đúng? - Tôi thực sự tò mò về phương pháp nào đưa ra quyết định này và làm thế nào?

Bạn vui lòng xác nhận. Plus, tôi đã nhận được một lỗi theo cách tiếp cận này nhưng thêm myObject = nil sau khi phát hành myObject trong dealloc phương pháp của lớp điều khiển cố định vấn đề. Cảm ơn.

Trả lời

12

Đây là một câu hỏi cũ, nhưng tôi không thấy một câu trả lời thích hợp, vì vậy ở đây đi:

Khi một cảnh báo bộ nhớ được nhận, -didReceiveMemoryWarning được gọi trong TẤT CẢ các bộ điều khiển xem, cho dù họ là những "hiện tại" một hay không. Các bộ điều khiển xem chỉ đơn giản là lắng nghe phát sóng sự kiện cảnh báo bộ nhớ.

Nếu chế độ xem của bộ điều khiển chế độ xem không được sử dụng tại thời điểm cảnh báo bộ nhớ, bộ điều khiển sẽ giải phóng nó bằng cách đặt thuộc tính thành không. Làm cách nào để biết liệu chế độ xem có được sử dụng không? Theo thuộc tính -superview của chế độ xem. Nếu view.superview là không, thì chế độ xem không phải là một phần của bất kỳ cây nào và có thể được tải xuống an toàn.

Khi điều đó xảy ra, bộ điều khiển -viewDidUnload được gọi. Đây là địa điểm chính xác để dỡ bất kỳ cửa hàng nào và mọi thứ sẽ được tạo lại trong -viewDidLoad.


Vì vậy, -didReceiveMemoryWarning là gì? Bộ điều khiển của bạn có thể có các đối tượng không được đưa vào cho đến khi được truy cập. Ví dụ, bạn có thể có một bộ điều khiển đôi khi cần một đoạn dữ liệu lớn từ một tệp, nhưng không phải lúc nào cũng vậy. Bạn có thể có một tài sản đặt ra cho nó như thế này:

- (NSData*)bigChunkOfData { 
    // Get data from our instance variable _data, read from disk if necessary 
    if (_data == nil) { 
    _data = [[NSData alloc] initWithContentsOfFile:@"/path/to/data"]; 
    } 
    return _data; 
} 

này sẽ đọc dữ liệu từ đĩa lần đầu tiên này, sau đó giữ nó trong một biến ví dụ. Vì biến số _data được tạo theo yêu cầu, chúng tôi có thể an toàn khi tải xuống trong các tình huống thiếu bộ nhớ: nó sẽ chỉ được tạo lại vào lần tiếp theo chúng ta cần nó.

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 

    [_data release]; 
    _data = nil; // <-- Very important: don't leave strong references dangling. 
} 
8

tôi làm sạch của tôi như thế này:

-(void)setView:(UIView*)view 
{ 
    [super setView:view]; 
    if(view == nil) 
    { 
     // Our view has been cleared, therefore we should clean up everything 
     // we are not currently using 
.... 

setView:nil được gọi bởi UIViewController để đáp ứng với một cảnh báo bộ nhớ, nếu xem đó không phải là hiện hữu - đó là cơ bản những gì bạn muốn biết.

EDITED

Trong câu trả lời cho những thăng sau:

  1. đúng.
  2. Đó là những gì tôi làm và nó phù hợp với tôi.
  3. Chính xác. Việc thực hiện didReceiveMemoryWarning trong UIViewController là những gì hiện này. Nếu bạn không ghi đè didReceiveMemoryWarning, sau đó thực hiện lớp cơ sở trong UIViewController sẽ được gọi là - nếu bạn làm ghi đè lên nó, rõ ràng là bạn nên gọi:

    [super didReceiveMemoryWarning] 
    
+0

Thậm chí nếu tôi không ghi đè phương pháp didReceiveMemoryWarning, quan điểm của tôi sẽ bị xóa. Tại sao vậy? – Mustafa

+1

Không ghi đè có nghĩa là bạn nhận được hành vi mặc định do UIViewController triển khai, để xóa chế độ xem của bạn. Nếu ghi đè của bạn chỉ đơn giản gọi các siêu thực hiện, đó là giống như không có ghi đè ở tất cả. –

1

Đối với những lời cảnh báo điểm quản lý và bộ nhớ:

UIKit không chỉ cho phép điều hướng trở lại từ bộ điều khiển chế độ xem mà còn cho phép điều hướng đến các bộ điều khiển chế độ xem khác từ bộ điều khiển chế độ xem hiện tại. Trong trường hợp này, một UIViewController mới sẽ được cấp phát và sau đó được tải vào dạng xem. Bộ điều khiển chế độ xem cũ sẽ tắt màn hình và trở nên không hoạt động nhưng vẫn sở hữu nhiều đối tượng - một số thuộc tính tùy chỉnh và biến và các đối tượng khác trong thuộc tính/phân cấp chế độ xem. Và bộ điều khiển chế độ xem có thể nhìn thấy mới, liên quan đến các đối tượng xem của nó.

Do số lượng bộ nhớ hạn chế của thiết bị di động, sở hữu hai bộ đối tượng - một trong bộ điều khiển chế độ xem màn hình và một trong bộ điều khiển chế độ xem trên màn hình - có thể quá nhiều để xử lý. Nếu UIKit cho rằng cần thiết, nó có thể đòi lại một số bộ nhớ của bộ điều khiển chế độ xem màn hình không được hiển thị; UIKit biết bộ điều khiển xem nào là trên màn hình và màn hình ngoài màn hình, như sau khi tất cả, nó là một trong những quản lý chúng (khi bạn gọi presentModalViewController:animated: hoặc dismissModalViewControllerAnimated:). Vì vậy, mỗi khi nó cảm thấy áp lực, UIKit tạo ra cảnh báo bộ nhớ, loại bỏ và giải phóng chế độ xem màn hình của bạn khỏi hệ thống phân cấp, sau đó gọi phương thức viewDidUnload tùy chỉnh của bạn để làm tương tự cho các thuộc tính và biến của bạn. UIKit tự động phát hành tự động, cho phép chúng tôi phát hành các biến và thuộc tính của mình theo cách thủ công trong mã viewDidUnload của chúng tôi. Nó làm như vậy cho tất cả các bộ điều khiển xem màn hình ngoài màn hình.

Khi hệ thống hết bộ nhớ, hệ thống sẽ kích hoạt didReceiveMemoryWarning. Chế độ xem trên màn hình sẽ được khôi phục và phát hành khi cảnh báo bộ nhớ, nhưng chế độ xem trên màn hình của bạn sẽ không được phát hành - nó hiển thị và cần thiết. Trong trường hợp lớp học của bạn sở hữu rất nhiều bộ nhớ, chẳng hạn như bộ nhớ cache, hình ảnh hoặc tương tự, didReceiveMemoryWarning là nơi bạn nên thanh lọc chúng, ngay cả khi chúng ở trên màn hình; nếu không, ứng dụng của bạn có thể bị chấm dứt do đóng tài nguyên hệ thống. Bạn cần ghi đè phương pháp này để đảm bảo bạn dọn sạch bộ nhớ của mình; chỉ cần nhớ bạn gọi [super didReceiveMemoryWarning];.

Một thậm chí phức tạp hơn giải thích hiện có sẵn ở đây: http://myok12.wordpress.com/2010/11/30/custom-uiviewcontrollers-their-views-and-their-memory-management/

0

May mắn thay, trình mô phỏng có chức năng tiện dụng cho phép bạn đặt các tình huống bộ nhớ thấp vào thử nghiệm. Đặt một số báo cáo NSLog() trong cả hai viewDidLoad và didReceiveMemoryWarning, như thế này: 

- (void)viewDidLoad { 
    NSLog(@"viewDidLoad"); 
    ... 
} 

- (void)didReceiveMemoryWarning { 
    NSLog(@"didReceiveMemoryWarning"); 
} 
Các vấn đề liên quan