2012-09-22 13 views
11

W urządzeniach z systemem iOS 6, i viewDidUnload są one nieaktualne, a kontrolery UIViewController nie rozładowują już widoków, które nie są widoczne na ekranie podczas ostrzeżenia o pamięci. Model View Controller Programming Guide ma przykład ręcznego przywrócenia tego zachowania.Jaki jest właściwy sposób usuwania widoków w systemie iOS 6 w ostrzeżeniu o pamięci (usterka dokumentu Apple)?

Oto przykładowy kod:

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Add code to clean up any of your own resources that are no longer necessary. 
    if ([self.view window] == nil) 
    { 
     // Add code to preserve data stored in the views that might be 
     // needed later. 

     // Add code to clean up other strong references to the view in 
     // the view hierarchy. 
     self.view = nil; 
    } 
} 

Poniżej próbki kodu jest następująca uwaga:

Następnym razem właściwość widok jest dostępny, widok jest przeładowane dokładnie jak to było pierwszy raz.

Jest tu widoczna wada. Jeśli kontroler widoku, który nie załadował swojego widoku, otrzyma ostrzeżenie o pamięci, załaduje swój widok w linii if ([self.view window] == nil), a następnie przystąpi do czyszczenia i zwolnienia go ponownie. W najlepszym przypadku jest to nieefektywne. W najgorszym przypadku pogorszy to warunki pamięci, jeśli załadowana zostanie złożona hierarchia widoku i dane pomocnicze. Sprawdziłem to zachowanie w symulatorze iOS.

Mogę z pewnością kodować wokół tego, ale wydaje się dziwne, że dokumenty Apple mają taki błąd. Czy czegoś brakuje?

Odpowiedz

17

Prawidłowa kontrola w kontrolerze widoku dla widoku ładowany i na ekranie jest:

if ([self isViewLoaded] && [self.view window] == nil)

Moje pełne rozwiązanie w iOS 6 mieć kontroler widok wyładować poglądy i oczyszczanie podobne do iOS 5 jest następujące:

// will not be called in iOS 6, see iOS docs 
- (void)viewWillUnload 
{ 
    [super viewWillUnload]; 
    [self my_viewWillUnload]; 
} 

// will not be called in iOS 6, see iOS docs 
- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    [self my_viewDidUnload]; 
} 

// in iOS 6, view is no longer unloaded so do it manually 
- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    if ([self isViewLoaded] && [self.view window] == nil) { 
    [self my_viewWillUnload]; 
    self.view = nil; 
    [self my_viewDidUnload]; 
    } 
} 

- (void)my_viewWillUnload 
{ 
    // prepare to unload view 
} 

- (void)my_viewDidUnload 
{ 
    // the view is unloaded, clean up as normal 
} 
+0

Czy są tam 'viewDidUnload' i' viewWillUnload' dla kompatybilności wstecznej? Jeśli tak, proponuję skomentować kod, aby powiedzieć, że te dwie metody nie będą w ogóle wywoływane w iOS 6 (jako [UIViewController docs] (http://developer.apple.com/library/ios/#documentation /uikit/reference/UIViewController_Class/DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref/occ/instm/UIViewController/viewWillUnload) stan). –

+0

Dobra sugestia, thx. Gotowe. – XJones

+0

Czy nie byłoby * nieco * lepiej, gdyby można było wywołać '[self viewWillUnload]' i '[self viewDidUnload]' odpowiednio w '- didReceiveMemoryWarning' zamiast niestandardowego' - my_view {Will | Did} Unload'? – Ali

Powiązane problemy