Sviluppo iOS: come posso indurre avvisi di memoria insufficiente sul dispositivo?


91

Vorrei testare il corretto funzionamento della mia app in condizioni di memoria insufficiente, ma è difficile da testare. Come posso indurre avvisi di memoria insufficiente che attivano il metodo didReceiveMemoryWarning nelle mie visualizzazioni quando l'app è in esecuzione sul dispositivo, non sul simulatore? O quali sono alcuni modi in cui posso testare la mia app in queste possibili condizioni?

Il motivo per cui non posso utilizzare il simulatore è che la mia app utilizza Game Center e gli inviti non funzionano sul simulatore.

Risposte:


8

Per testare su un dispositivo, è sufficiente aggiungere del codice che periodicamente alloca grossi blocchi di memoria senza liberarlo (cioè perdita di proposito). Puoi farlo in un thread separato, o in risposta a un timer, o utilizzando qualsiasi meccanismo che ti consenta di testare e osservare il comportamento della tua applicazione.

Potresti anche scegliere di creare un'app separata che faccia qualcosa di simile ed è progettata per essere eseguita in background, se desideri riutilizzarla facilmente e / o testarla con più applicazioni.


7
non molto pratico. la soluzione per chiamare un metodo privato per i test è migliore
Daij-Djan

4
Non è una buona soluzione se vuoi guardare lo scenario del mondo reale. Stai paralizzando l'app a causa di una perdita non dovuta alla pressione della memoria. Questo è un male poiché quello che vuoi fare è testare come l'app risponde in uno stato di pressione della memoria elevata. Al rovescio della medaglia è più difficile capire quale sia il problema è una vera perdita o quella falsa che hai introdotto. Il metodo privato è migliore per i test come indicato di seguito.
fzaziz

2
Questa risposta non dovrebbe essere sottovalutata, poiché il secondo paragrafo è in realtà ciò che Apple dice di fare se vuoi testare il comportamento della tua app quando la memoria è davvero bassa.
opaco

1
La risposta sarebbe migliorata con un blocco di codice per eseguire questa allocazione!
pkamb

Sebbene la configurazione richieda più lavoro, questo è un test più realistico rispetto alla chiamata al metodo privato. Quando c'è davvero una pressione critica della memoria, la tua app sarà in grado di eseguire le azioni che le dici di fare? E quelle azioni allevieranno la situazione o la peggioreranno e faranno terminare iOS? Inoltre, il metodo privato non funziona per testare DISPATCH_SOURCE_TYPE_MEMORYPRESSURE.
jk7

278

Puoi chiamare il metodo privato :

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

Ricorda solo di usarlo solo durante il debug, altrimenti la tua app verrà rifiutata.


6
Sembra che questo codice simuli accuratamente l'avviso di memoria sul dispositivo. Grazie Enzo!
William Denniss

28
Invece di usarlo nel codice, eseguilo nel debugger. Basta fare una pausa ed entrarepo [[UIApplication sharedApplication]performSelector:@selector(_performMemoryWarning)]
orkoden

17
Invece di usare po, usa expr, cioèexpr (void)[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];
Andy

11
Nel debugger, non è necessario utilizzare la soluzione alternativa per non avere l'intestazione:expr (void)[[UIApplication sharedApplication] _performMemoryWarning]
OrangeDog

3
Per chiunque stia cercando di farlo con Swift: digita expr UIApplication.sharedApplication().performSelector("_performMemoryWarning")invece di usare il solito#selector
funct7

27

La Simulate Memory Warningvoce di menu del simulatore iOS consente di simulare un avviso di memoria.


L'unico modo per verificarlo sul dispositivo è forzarlo effettivamente, ovvero utilizzando l'app per lunghi periodi di tempo o immagini intense o quello che hai, varierà da app a app. Un suggerimento potrebbe essere quello di utilizzare un dispositivo più vecchio (3g forse?) Invece di un iPhone 4 per aiutarti a ottenere l'avviso più velocemente.
Jesse Naugher

Grazie, Jesse, penso che aggiungerò solo alcuni hack alla mia app per simulare gli inviti in modo da poterlo eseguire nel simulatore e indurre gli avvisi di memoria in questo modo.
BeachRunnerFred

10
La domanda riguardava la simulazione sul dispositivo.
KPM

20

Utilizzando gli strumenti, utilizzare la voce di menu: Strumento -> Simula avviso di memoria.

Per utilizzare gli strumenti sulla tua app da Xcode, utilizza la voce di menu Prodotto -> Profilo.


Questo è anche meglio.
Zappel

@OrangeDog Cosa sta succedendo?
ThomasW

2
Beh, niente. Quando uso le risposte di Enzo, le visualizzazioni devono essere ricaricate quando ci ritorno, non utilizzando questo metodo.
OrangeDog

12

Ho riscritto la risposta di Enzo Tran in Swift:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)

Grazie! Xcode avverte di "nessun metodo dichiarato con il selettore Objective-C", ma funziona comunque.
man1

10

Se qualcuno, per qualsiasi motivo, tenta di farlo in Swift 4, ecco come allocare 1,2 GB di RAM.

let d = Data.init(repeating: 100, count: 1200000000)
  • Ciò è utile per attivare un avviso di avviso in altre app

Fare qualcosa di simile offuscherà le effettive informazioni sulla memoria che sto cercando di visualizzare in Instruments? Anche se vedo che non c'è un modo corretto per farlo su un dispositivo fisico, se il mio punto è vedere cosa sta occupando la mia memoria all'interno della mia app, sembra che questo distorcerà tutti i dati e io no avere più una risposta relativa. Vedrò ancora cosa sta prendendo di più , ma non le vere proporzioni.
Jake T.

questo si blocca immediatamente
Daniel Springer il

7

C'è un comando di menu che lo richiamerà.

Hardware > Simulate Memory Warning dal simulatore.


8
La domanda riguardava la simulazione sul dispositivo.
KPM

2
In Xcode 10 è ora in Debug> Simula avviso di memoria.
Sebbo

7

Convertito @ChikabuZ in swift 3:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)

4

Se qualcuno, per qualsiasi motivo, tenta di farlo in Swift 3, ecco come allocare 1,2 GB di RAM.

   for i in 0...1200 {
      var p: [UnsafeMutableRawPointer] = []
      var allocatedMB = 0
      p.append(malloc(1048576))
      memset(p[allocatedMB], 0, 1048576);
      allocatedMB += 1;
   }

3
let d = Data.init (ripetizione: 100, conteggio: 1200000000)
Adobels

2
@Adobels dovresti pubblicarlo come risposta :)
Koen.

1

Swift 4:

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

Può eseguire quanto sopra in risposta a un evento / notifica.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.