2011-10-17 13 views
7

To jest mniej pytanie, a raczej zapis tego, co znalazłem wokół przykładowego kodu AVCam dostarczonego przez Apple dla iOS4 i 5 manipulacji kamerą. Objawem tego problemu było to, że moja aplikacja zawiesiła się po uruchomieniu kontrolera AVCamViewController po zrobieniu około 5-10 zdjęć.Niskie ostrzeżenie o AVCam

Uruchomiłem aplikację za pomocą narzędzia do profilowania wycieków pamięci i nie było żadnych widocznych wycieków, ale po sprawdzeniu za pomocą Monitora aktywności odkryłem, że coś o nazwie mediaserverd zwiększało się o 17 Mb za każdym razem, gdy kamera została uruchomiona i kiedy osiągnęło ~ 100Mb aplikacji rozbił się z wieloma ostrzeżeniami o małej pamięci.

+0

Dzięki! Proszę podzielić odpowiedź na odpowiedź, którą następnie można zaakceptować: [Etykieta odpowiedzi na własne pytanie] (http://meta.stackexchange.com/questions/17845/etiquette- na -answering-your-own-question) i [Zamieszczanie i udzielanie odpowiedzi na pytania, na które już znalazłeś odpowiedź] (http://meta.stackexchange.com/questions/2706/posting-and-answering-questions-you-ha---)--). – sehe

+0

Próbowałem tego, ale ponieważ nie jestem użytkownikiem klasy premium, nie pozwoliłbym sobie odpowiedzieć na moje własne pytanie w ciągu 24 godzin ... nie miałem czasu, żeby z nim pogodzić (lub zapomnieć o tym, co chciałem nagrać) ... Zobaczę, czy mogę to teraz zrobić. –

Odpowiedz

4

Jabłko zmieniony przykładowy kod na 17 października 2013 roku, ustalające cykl zatrzymania. Problem jest spowodowany niewłaściwym użyciem self w blokach zdefiniowanych w init.

Oto opis rewizja

Poprawiono zachować cykli AVCaptureManager które powodują przecieków. UWAGA: - jeśli zaadaptowałeś kod AVCam w swojej aplikacji, powinieneś przyjąć poprawki wprowadzone tutaj w metodzie AVCaptureManager.m 'init. Bez tych poprawek mogą wystąpić nieszczelności AVCaptureManager i pozostawiać aparat bez przerwy uruchomiony, gdy aplikacja znajduje się na pierwszym planie.


Jednak, poprawka wprowadzono działa tylko w przypadku podręcznika Utrzymał się liczyć. Jeśli używasz ARC w projekcie, oprócz pozbycia się połączeń release/retain i innych oczywistych rzeczy, kwalifikator przestrzeni dyskowej dla weakSelf musi zostać zmieniony z __block na __weak, jak poniżej.

__weak AVCamCaptureManager *weakSelf = self; 

W rzeczywistości semantyczna z __block zmieniona z ARC. W MRC spowodowało to, że zmienna była słabo przywoływana, ale w ARC jej nie ma i do tego celu musi być użyty __weak.

Więcej informacji na ten temat można znaleźć tutaj: How do I avoid capturing self in blocks when implementing an API?

Dzięki nowej init realizację od ostatniego przeglądu i korzystania __weak zamiast __block wreszcie spowodował metoda dealloc być właściwie nazywa.


Wreszcie dla tych, którzy nie lubią nosić ze starego kodu starszego typu, tutaj jest zmodernizowana wersja projektu AVCam: https://github.com/Gabro/AVCam

Cechy:

  • pamięci przecieki darmo
  • używa ARC
  • nowoczesna składnia Cel-C
  • podrzędny interfejs użytkownika poprawki dla iOS 7
+0

Cześć Gabriele, rzuciłem okiem na twój projekt AVCam. Możesz zmienić komentarz "zgodny z ARC" na "ARC exclusive"? Dodałem go do mojego projektu niezwiązanego z ARC i są pewne awarie kompilacji związane z używaniem wyłącznej funkcjonalności ARC. –

+0

@RedNightingale Absolutnie, okropny wybór słów. Przy okazji możesz selektywnie włączyć ARC dla określonych plików, nawet jeśli nie lubisz ARC. Mam nadzieję, że to pomoże. –

+0

Zajrzę do tego. Wypróbowałem nowe wersje kodu Apple i wydaje się, że w końcu działają poprawnie, więc będę promować to jako odpowiedź. –

16

Pierwszą rzeczą, którą zrobiłem było umieszczenie logowania w dealloc metodach wszystkich plików AVCam. Szybko odkryłem, że AVCamCaptureManager i AVCamRecorder nie zostały zwolnione, gdy był AVCamViewController. Sprawdziłem zachowanie i zwalniałem połączenia i wyglądało na to, że balansują, więc ustawiłem punkt przerwania w wydaniu [captureManager] i odkryłem, że miał on wartość 2 po wydaniu (i dlatego nie wywołano dealloc AVCamCapture Manager).

Następnie przeszedłem przez proces tworzenia menedżera przechwytywania i odkryłem, że ma on liczbę zachowań równą 3 natychmiast po wywołaniu metody init.

Stepping dzięki metodzie init oraz sprawdzenie zachować liczyć na każdej linii odkryłem następujące dwa wiersze były zarówno zwiększając Hrabia zachować:

[self setDeviceConnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasConnectedNotification object:nil queue:nil usingBlock:deviceConnectedBlock]]; 
[self setDeviceDisconnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasDisconnectedNotification object:nil queue:nil usingBlock:deviceDisconnectedBlock]]; 

pominie znalazłem, że partnerami removeObserver były wewnątrz metody dealloc z AVCamCaptureManager (który nie był o nazwie), a więc liczba zachowują nigdy nie spadła do 0.

aby go naprawić ja stworzył nową metodę removeObservers publicznej:

-(void)removeObservers { 
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 
    [notificationCenter removeObserver:[self deviceConnectedObserver]]; 
    [notificationCenter removeObserver:[self deviceConnectedObserver]]; 
} 

i wykonanie tych samych linii poza metodą dealloc AVCamCaptureManager.

Wywołanie [captureManager removeObservers]; i NASTĘPNIE dzwoniąc [releaseManager release]; w metodzie dealloc AVCamViewController z powodzeniem pomniejsza liczbę zatrzymań do 0.

Testowanie za pomocą Monitora aktywności ma teraz proces serwera multimediów nuci tylko 5-17Mb, a zawieszenie się zatrzymuje!

Mam nadzieję, że to pomoże każdemu, kto ma ten problem!

+1

Lepiej ... potężni bogowie SO pozwolili mi odpowiedzieć na moje własne pytanie;) –

+0

Potężni bogowie SO pozwolili mi podziękować, podając mi moje +1;) – sehe

+0

Dobry opis. Uważam, że trafiliśmy na ten sam problem. –

2

Niedawno pojawił się ten problem. Odkryłem, że prawdziwym problemem jest to, że deviceConnectedBlock i deviceDisconnectedBlock domyślnie odnoszą się do siebie, co prowadzi do zachowania cykli. Aby to naprawić, zmień wszystkie odwołania do ivar w tych blokach, aby użyć weakSelf.

W ten sposób nie trzeba pamiętać, aby wyraźnie wywołać metodę podziału.

Mam nadzieję, że to pomoże komuś innemu.

REF: View controller dealloc not called when using NSNotificationCenter code block method with ARC

+0

Miałem jedno odniesienie do siebie w bloku.Zamieniłem to na weakSelf i powróciłem do "normalnego" kodu zwalniającego AVCAM. Program CaptureManager nadal nie wywołuje dealloc. Artykuł, do którego odnośnik się odnosi, odnosi się do __weak w celach referencyjnych, ale dotyczy to tylko kodu ARC (którego aktualnie nie używam). Muszę użyć __block zamiast, ale nie rozumiem wystarczająco dużo o "blokach", aby móc wymyślić równoważne rozwiązanie, które działa. –

Powiązane problemy