Rozwój iOS: Jak wywołać ostrzeżenia o małej ilości pamięci na urządzeniu?

93

Chciałbym sprawdzić, czy moja aplikacja działa dobrze w warunkach małej ilości pamięci, ale jest to trudne do przetestowania. Jak mogę wywołać ostrzeżenia o małej ilości pamięci, które wyzwalają metodę didReceiveMemoryWarning w moich widokach, gdy aplikacja jest uruchomiona na urządzeniu, a nie na symulatorze? Albo jakie są sposoby na przetestowanie aplikacji w tych możliwych warunkach?

Nie mogę używać symulatora, ponieważ moja aplikacja korzysta z Game Center, a zaproszenia nie działają na symulatorze.

BeachRunnerFred
źródło

Odpowiedzi:

9

Aby przetestować na urządzeniu, po prostu dodaj kod, który okresowo przydziela duże fragmenty pamięci bez jej zwalniania (tj. Celowo wycieka). Możesz to zrobić w osobnym wątku, w odpowiedzi na licznik czasu lub przy użyciu dowolnego mechanizmu, który najlepiej pozwala na testowanie i obserwowanie zachowania aplikacji.

Możesz także utworzyć oddzielną aplikację, która robi coś podobnego i jest zaprojektowana do działania w tle, jeśli chcesz łatwo ponownie użyć tej aplikacji i / lub przetestować ją z wieloma aplikacjami.

BinaryStar
źródło
7
niezbyt praktyczne. lepszym rozwiązaniem jest wywołanie prywatnej metody testowania
Daij-Djan
5
Nie jest to dobre rozwiązanie, jeśli chcesz spojrzeć na scenariusz z prawdziwego świata. Uszkadzasz aplikację z powodu wycieku, a nie z powodu presji pamięci. To źle, ponieważ to, co chcesz zrobić, to przetestować, jak aplikacja reaguje w stanie wysokiego obciążenia pamięci. Z drugiej strony trudniej jest ustalić, na czym polega prawdziwy wyciek lub fałszywy, który wprowadziłeś. Metoda prywatna jest lepsza do testowania, jak podano poniżej.
fzaziz
2
Nie należy lekceważyć tej odpowiedzi, ponieważ drugi akapit jest właściwie tym, co Apple mówi, aby zrobić, jeśli chcesz przetestować zachowanie aplikacji, gdy pamięć jest naprawdę niska.
mat.
1
Odpowiedź byłaby ulepszona za pomocą bloku kodu do wykonania tej alokacji!
pkamb
Chociaż konfiguracja wymaga więcej pracy, jest to bardziej realistyczny test niż wywołanie metody prywatnej. Kiedy naprawdę występuje krytyczne obciążenie pamięci, czy Twoja aplikacja będzie w stanie wykonać polecenia, które jej nakazujesz? Czy te działania złagodzą sytuację, czy ją pogorszą i spowodują, że iOS ją zakończy? Poza tym metoda prywatna nie działa do testowania DISPATCH_SOURCE_TYPE_MEMORYPRESSURE.
jk7
278

Możesz wywołać metodę prywatną :

[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];

Pamiętaj tylko, aby używać go tylko do debugowania, w przeciwnym razie Twoja aplikacja zostanie odrzucona.

Enzo Tran
źródło
6
Wygląda na to, że ten kod dokładnie symuluje ostrzeżenie dotyczące pamięci na urządzeniu. Dzięki Enzo!
William Denniss
28
Zamiast używać tego w kodzie, wykonaj go w debugerze. Po prostu naciśnij pauzę i wejdźpo [[UIApplication sharedApplication]performSelector:@selector(_performMemoryWarning)]
orkoden
17
Zamiast używać po, użyj wyrażenia, np.expr (void)[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];
Andy
11
W debugerze nie musisz stosować obejścia, aby nie mieć nagłówka:expr (void)[[UIApplication sharedApplication] _performMemoryWarning]
OrangeDog
3
Dla każdego, kto chce to zrobić za pomocą Swift: wpisz expr UIApplication.sharedApplication().performSelector("_performMemoryWarning")zamiast zwykłego#selector
funct7
29

Simulate Memory WarningPozycja menu symulatora iOS umożliwia symulację ostrzeżenia dotyczącego pamięci.

Ole Begemann
źródło
Jedynym sposobem sprawdzenia tego na urządzeniu jest faktyczne wymuszenie tego, tj. Używanie aplikacji przez długi czas lub intensywne obrazy lub to, co masz, będzie się różnić w zależności od aplikacji. Sugestią może być użycie starszego urządzenia (może 3g?) Zamiast iPhone'a 4, aby szybciej uzyskać ostrzeżenie.
Jesse Naugher
Dzięki, Jesse, myślę, że po prostu dodam kilka hacków do mojej aplikacji, aby zasymulować zaproszenia, aby móc uruchomić ją w symulatorze i w ten sposób wywołać ostrzeżenia dotyczące pamięci.
BeachRunnerFred
10
Pytanie dotyczyło symulacji na urządzeniu.
KPM
20

Używając Instrumentów, użyj pozycji menu: Instrument -> Symulacja ostrzeżenia pamięci.

Aby używać instrumentów w swojej aplikacji z Xcode, użyj pozycji menu Produkt -> Profil.

Thomas W.
źródło
To jest jeszcze lepsze.
Zappel
@OrangeDog Co się dzieje?
Thomas W
2
Jak nic. Kiedy używam odpowiedzi Enzo, widoki muszą się ponownie ładować, kiedy do nich wracam, a nie przy użyciu tej metody.
OrangeDog
12

Mam ponownie napisany odpowiedź Enzo Tran w Swift:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)
ChikabuZ
źródło
Dzięki! Xcode ostrzega przed „brakiem metody zadeklarowanej za pomocą selektora Objective-C”, ale to działa.
man1
10

Jeśli ktoś z jakiegoś powodu spróbuje to zrobić w Swift 4 - oto jak przeznaczyć 1,2 GB pamięci RAM.

let d = Data.init(repeating: 100, count: 1200000000)
  • Jest to pomocne przy uruchamianiu ostrzeżenia w innych aplikacjach
Błażej SLEBODA
źródło
Czy zrobienie czegoś takiego zaciemni rzeczywiste informacje w pamięci, które próbuję wyświetlić w Instruments? Chociaż widzę, że nie ma właściwego sposobu, aby to zrobić na urządzeniu fizycznym, jeśli chodzi mi o sprawdzenie, co zajmuje moją pamięć w mojej aplikacji, wydaje się, że spowoduje to wypaczenie wszystkich danych, a ja nie mają już względną odpowiedź. Nadal zobaczę, co zajmuje więcej , ale nie prawdziwe proporcje.
Jake T.
to się zawiesza natychmiast
Daniel Springer
8

Przekonwertowano @ChikabuZ na swift 3:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)
kindaian
źródło
7

Istnieje polecenie menu, które go wywoła.

Hardware > Simulate Memory Warning z symulatora.

Daniel A. White
źródło
8
Pytanie dotyczyło symulacji na urządzeniu.
KPM
2
W Xcode 10 jest teraz pod ostrzeżeniem Debug> Simulate Memory.
Sebbo
4

Jeśli ktoś z jakiegoś powodu spróbuje to zrobić w Swift 3 - oto jak przeznaczyć 1,2 GB pamięci RAM.

   for i in 0...1200 {
      var p: [UnsafeMutableRawPointer] = []
      var allocatedMB = 0
      p.append(malloc(1048576))
      memset(p[allocatedMB], 0, 1048576);
      allocatedMB += 1;
   }
ph1lb4
źródło
3
let d = Data.init (powtarzanie: 100, liczba: 1200000000)
Blazej SLEBODA
2
@Adobels powinieneś to zamieścić jako odpowiedź :)
Koen.
1

Swift 4:

UIApplication.shared.perform (Selector (("_ performMemoryWarning")))

Może wykonać powyższe w odpowiedzi na zdarzenie / powiadomienie.

Vishal Chaudhry
źródło