5

Chciałbym dowiedzieć się więcej o zarządzaniu pamięcią w Objective-C, co nie jest takie proste, ponieważ jestem dość nowy w Objective-C i ARC i jestem głównie przy pisaniu języków, dla których nie muszę tak wiele (lub wcale) radzić sobie z zarządzaniem pamięcią.Kiedy kontroler widoku zostanie zwolniony, czy powinien opróżnić pamięć?

Aplikacja, nad którą pracuję, prezentuje kod viewController (z załączonym plikiem xib) z kodu po naciśnięciu przycisku. W tym kontroler widoku mam kilka widoków utworzonych; Nagrywam sekwencję obrazów (zdjęcie z kamery, zapisanych na dysku), które zamieniam na film i mam tracker GPS (mapKit), który wyświetla trochę mapy na ekranie. Mimo wszystko odbywa mogę wcisnąć przycisk „Gotowe”, która wywołuje [self dismissViewControllerAnimated:YES completion:nil];

viewController jest animowany z powrotem do mojego rootViewController i dlatego kładę komunikat NSLog wewnątrz metody w viewController dealloc która jest oddalona mogę potwierdzić tej viewController jest zwalniany.

Problem polega na tym, że widzę wzrost pamięci po użyciu aplikacji (użycie składa się z robienia zdjęć i rejestrowania lokalizacji GPS na mapie MapKit oraz generowania pliku filmowego) do około 80 MB i spada do około 70 MB po naciśnięciu przycisku "done", aby viewController został odrzucony, a aplikacja wraca do mojego rootViewController. Mogę ponownie zaprezentować ten sam viewController, użyć go i odrzucić, a aplikacja będzie nadal zajmować około 70 MB pamięci, która nie spada. To naprawdę nie wygląda na wyciek pamięci do mnie, ponieważ w takim przypadku spodziewałbym się stałego wzrostu pamięci przy każdym utworzeniu i zwolnieniu kontrolki viewController. Nie dzieje się tak, nawet jeśli mam różne przyciski w moim rootViewController, które wszystkie tworzą instancję nowego i unikalnego wystąpienia mojej klasy viewController.

Zastanawiam się: czy jest coś, czego powinienem szukać, czy jest to oczekiwane zachowanie? Może aplikacja buforuje klasy do wykorzystania w przyszłości? Czy przy prawidłowym zarządzaniu pamięcią powinienem oczekiwać, że aplikacja powróci do stanu "pierwotnego" pamięci (w tym przypadku będzie to około 4 MB) po zwolnieniu jedynego wyświetlonego kontrolera viewController?

+1

Profiluj aplikację, używając * Wycieków * w obszarze "Instrumenty". – trojanfoe

+0

Gotowe, nie wykryto wycieków. – Hype1

+0

Możesz przeczytać [ten Q & A] (http://stackoverflow.com/q/12641658/335858), mówi o problemie z pamięcią MapKit. Pytania i odpowiedzi są jednak stare, więc mogły zostać rozwiązane. – dasblinkenlight

Odpowiedz

6

Jeśli widzisz ten wzrost pamięci w Xcode, a nie przy użyciu instrumentów następnie the answer I have come up with is in this answer.

można przeczytać, że cała odpowiedź, to jest całkiem w głębi.Krótko mówiąc, w Xcode widzisz ilość pamięci, którą system operacyjny "dał" twojej aplikacji. To zwiększy się za każdym razem, gdy aplikacja spróbuje coś przydzielić. Nie zmniejsza się tak szybko, ponieważ system operacyjny domyślnie zakłada, że ​​Twoja aplikacja może potrzebować więcej pamięci w przyszłości. System operacyjny szybciej opuszcza tę pamięć "podaną" w aplikacji, niż ją zabiera i oddaje później.

+1

Wow, wielkie dzięki! Szukałem błędów w kodzie aplikacji i odczytywałem ARC i zarządzanie pamięcią przez cały dzień i nigdy nie przyszło mi do głowy, że wartość pamięci miałaby coś wspólnego z pamięcią przypisaną przez system operacyjny, a nie w rzeczywistości potrzebną w tym momencie. Miałem tylko tę aplikację aktywną i na potrzeby testu aktywowałem kilka gier 3D, a potem zauważyłem, że zużycie pamięci przez moją aplikację natychmiast spada. Straciłem dzień pracy, ale sporo się nauczyłem. :) – Hype1

2

Kontroler widoku powinien zostać usunięty z pamięci, gdy nie jest używany przez inne obiekty (lub nie ma silnych połączeń z innymi obiektami, które nie zostały jeszcze usunięte z pamięci).

Przykł.

class ViewController: UIViewController { 
    var secondViewController: SecondViewController? 
    override func viewDidLoad() { 
     super.viewDidLoad() 
    } 
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
     if let identifier = segue.identifier { 
      if identifier == "second" { 
       if secondViewController == nil { 
        secondViewController = segue.destinationViewController as? SecondViewController 
       } else { 
        println("There's still an instance of second view controller") 
       } 
      } 
     } 
    } 
} 

Powiedzmy, że przedstawił secondViewController po raz pierwszy za pomocą storyboard segue i przechowywać go w instancji ViewController jako właściwość. Następnie odrzucisz drugi kontrolerViewView i ponownie wyświetlisz drugi kontroler ViewViewer z ViewController, który wyświetli komunikat "Nadal istnieje instancja drugiego kontrolera widoku", ponieważ ten, który wcześniej przedstawiłeś, był nadal używany przez ViewController.

Jednak gdy secondViewController ma słabe połączenie, (weak var secondViewController: SecondViewController), nigdy się nie drukuje, ponieważ od momentu odrzucenia drugiego kontroleraViewViewer zostanie on usunięty z pamięci, a drugi kontroler będzie zerowy.

EDIT:

Uwaga: Wynik powinien być taki sam przy użyciu Objective-C.

+0

Dzięki za poświęcony czas i wysiłek, ale @ Putz1103 właśnie udzielił mi odpowiedzi, której potrzebowałem. – Hype1

Powiązane problemy