Développement iOS: comment puis-je induire des avertissements de mémoire insuffisante sur l'appareil?

91

J'aimerais bien tester les fonctions de mon application dans des conditions de mémoire faible, mais c'est difficile à tester. Comment puis-je induire des avertissements de mémoire insuffisante qui déclenchent la méthode didReceiveMemoryWarning dans mes vues lorsque l'application s'exécute sur l'appareil, pas sur le simulateur? Ou comment puis-je tester mon application dans ces conditions possibles?

La raison pour laquelle je ne peux pas utiliser le simulateur est que mon application utilise Game Center et que les invitations ne fonctionnent pas sur le simulateur.

BeachRunnerFred
la source

Réponses:

8

Pour tester sur un appareil, il suffit d'ajouter du code qui alloue périodiquement de gros morceaux de mémoire sans le libérer (c'est-à-dire une fuite intentionnelle). Vous pouvez le faire dans un thread distinct, ou en réponse à un minuteur, ou en utilisant le mécanisme qui vous permet le mieux de tester et d'observer le comportement de votre application.

Vous pouvez également choisir de créer une application distincte qui fait quelque chose de similaire et est conçue pour s'exécuter en arrière-plan, si vous souhaitez facilement la réutiliser et / ou la tester avec plusieurs applications.

BinaryStar
la source
7
pas très pratique. la solution pour appeler une méthode privée de test est meilleure
Daij-Djan
4
Ce n'est pas une bonne solution si vous voulez regarder un scénario du monde réel. Vous paralysez l'application en raison d'une fuite non due à une pression de mémoire. C'est mauvais car ce que vous voulez faire est de tester la réponse de l'application dans un état de pression mémoire élevée. En revanche, il est plus difficile de déterminer quel est le problème d'une vraie fuite ou du faux que vous avez introduit. La méthode privée est meilleure pour les tests, comme indiqué ci-dessous.
fzaziz
2
Cette réponse ne doit pas être rejetée, car le deuxième paragraphe est en fait ce qu'Apple dit de faire si vous souhaitez tester le comportement de votre application lorsque la mémoire est vraiment faible.
mat
1
La réponse serait améliorée avec un bloc de code pour effectuer cette allocation!
pkamb
Bien que la configuration demande plus de travail, il s'agit d'un test plus réaliste que d'appeler la méthode privée. Lorsqu'il y a vraiment une pression mémoire critique, votre application pourra-t-elle effectuer les actions que vous lui demandez de faire? Et ces actions vont-elles soulager la situation ou l'aggraver et amener iOS à y mettre fin? En outre, la méthode privée ne fonctionne pas pour tester DISPATCH_SOURCE_TYPE_MEMORYPRESSURE.
jk7
278

Vous pouvez appeler la méthode privée :

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

N'oubliez pas de l'utiliser uniquement lors du débogage, sinon votre application sera rejetée.

Enzo Tran
la source
6
Il semble que ce code simule avec précision l'avertissement de mémoire sur l'appareil. Merci Enzo!
William Denniss
28
Au lieu de l'utiliser dans le code, exécutez-le dans le débogueur. Appuyez simplement sur pause et entrezpo [[UIApplication sharedApplication]performSelector:@selector(_performMemoryWarning)]
orkoden
17
Plutôt que d'utiliser po, utilisez expr, ieexpr (void)[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];
Andy
11
Dans le débogueur, vous n'avez pas besoin d'utiliser la solution de contournement pour ne pas avoir l'en-tête:expr (void)[[UIApplication sharedApplication] _performMemoryWarning]
OrangeDog
3
Pour tous ceux qui cherchent à faire cela avec Swift: tapez expr UIApplication.sharedApplication().performSelector("_performMemoryWarning")au lieu d'utiliser l'habituel#selector
funct7
27

L' Simulate Memory Warningélément de menu du simulateur iOS vous permet de simuler un avertissement de mémoire.

Ole Begemann
la source
Le seul moyen de le vérifier sur l'appareil est de le forcer, c'est-à-dire en utilisant l'application pendant de longues périodes ou en utilisant des images intensives ou autre, cela variera d'une application à l'autre. Une suggestion pourrait être d'utiliser un appareil plus ancien (3g peut-être?) Au lieu d'un iPhone 4 pour vous aider à obtenir l'avertissement plus rapidement.
Jesse Naugher
Merci, Jesse, je pense que je vais juste ajouter quelques hacks à mon application pour simuler des invitations afin que je puisse l'exécuter dans le simulateur et induire les avertissements de mémoire de cette façon.
BeachRunnerFred
10
La question concernait la simulation sur l'appareil.
KPM
20

À l'aide d'instruments, utilisez l'élément de menu: Instrument -> Simulate Memory Warning.

Pour utiliser Instruments sur votre application à partir de Xcode, utilisez l'élément de menu Produit -> Profil.

ThomasW
la source
C'est encore mieux.
Zappel
@OrangeDog Que se passe-t-il?
ThomasW
2
Eh bien, rien. Lorsque j'utilise les réponses d'Enzo, les vues doivent se recharger lorsque j'y reviens, pas si j'utilise cette méthode.
OrangeDog
12

J'ai réécrit la réponse d'Enzo Tran dans Swift:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)
ChikabuZ
la source
Merci! Xcode met en garde contre "aucune méthode déclarée avec le sélecteur Objective-C", mais cela fonctionne néanmoins.
man1
10

Si quelqu'un, pour une raison quelconque, essaie de le faire dans Swift 4 - voici comment allouer 1,2 Go de RAM.

let d = Data.init(repeating: 100, count: 1200000000)
  • Ceci est utile pour déclencher une alerte d'avertissement dans d'autres applications
Adobels
la source
Est-ce que faire quelque chose comme ceci obscurcira les informations de mémoire réelles que j'essaie de voir dans Instruments? Bien que je vois qu'il n'y a pas de moyen approprié de le faire sur un appareil physique, si mon objectif est de voir ce qui occupe ma mémoire dans mon application, il semble que cela va biaiser toutes les données et je ne le ferai pas. plus avoir une réponse relative. Je vais toujours voir ce qui prend le plus , mais pas les vraies proportions.
Jake T.
cela plante immédiatement
Daniel Springer le
7

Theres une commande de menu qui l'invoquera.

Hardware > Simulate Memory Warning du simulateur.

Daniel A. White
la source
8
La question concernait la simulation sur l'appareil.
KPM
2
Dans Xcode 10, c'est maintenant sous Debug> Simulate Memory warning.
Sebbo
7

Conversion de @ChikabuZ en Swift 3:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)
kindaian
la source
4

Si quelqu'un, pour une raison quelconque, essaie de le faire dans Swift 3 - voici comment allouer 1,2 Go de RAM.

   for i in 0...1200 {
      var p: [UnsafeMutableRawPointer] = []
      var allocatedMB = 0
      p.append(malloc(1048576))
      memset(p[allocatedMB], 0, 1048576);
      allocatedMB += 1;
   }
ph1lb4
la source
3
let d = Data.init (répétition: 100, nombre: 1200000000)
Adobels
2
@Adobels, vous devriez poster ça comme réponse :)
Koen.
1

Swift 4:

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

Peut exécuter ce qui précède en réponse à un événement / notification.

Vishal Chaudhry
la source