Desenvolvimento iOS: Como posso induzir avisos de pouca memória no dispositivo?

91

Gostaria de testar as funções do meu aplicativo bem em condições de pouca memória, mas é difícil de testar. Como posso induzir avisos de pouca memória que acionam o método didReceiveMemoryWarning em minhas visualizações quando o aplicativo está sendo executado no dispositivo, não no simulador? Ou de que maneiras posso testar meu aplicativo nessas condições possíveis?

Não consigo usar o simulador porque meu aplicativo usa o Game Center e os convites não funcionam no simulador.

BeachRunnerFred
fonte

Respostas:

8

Para testar em um dispositivo, basta adicionar algum código que aloca periodicamente grandes blocos de memória sem liberá-la (ou seja, vazamento proposital). Você pode fazer isso em um thread separado, ou em resposta a um cronômetro, ou usando qualquer mecanismo que melhor permita testar e observar o comportamento de seu aplicativo.

Você também pode optar por criar um aplicativo separado que faça algo semelhante e seja projetado para ser executado em segundo plano, se quiser reutilizá-lo facilmente e / ou testar com vários aplicativos.

BinaryStar
fonte
7
não é muito prático. a solução para chamar um método privado para teste é melhor
Daij-Djan
4
Não é uma boa solução se você deseja observar o cenário do mundo real. Você está paralisando o aplicativo devido a um vazamento, não devido à pressão da memória. Isso é ruim, pois o que você quer fazer é testar como o aplicativo responde em estado de alta pressão de memória. No lado negativo, é mais difícil descobrir qual é o problema: um vazamento real ou falso que você introduziu. O método privado é melhor para testar conforme mostrado abaixo.
fzaziz de
2
Esta resposta não deve ser rejeitada, pois o segundo parágrafo é realmente o que a Apple diz para fazer se você quiser testar o comportamento do seu aplicativo quando a memória realmente ficar baixa.
matt
1
A resposta seria melhorada com um bloco de código para realizar essa alocação!
pkamb
Embora exija mais trabalho para configurar, este é um teste mais realista do que chamar o método privado. Quando realmente há pressão crítica de memória, seu aplicativo será capaz de realizar as ações que você ordenar? E essas ações irão aliviar a situação ou torná-la pior e fazer com que o iOS a encerre? Além disso, o método privado não funciona para testar DISPATCH_SOURCE_TYPE_MEMORYPRESSURE.
jk7
278

Você pode chamar o método privado :

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

Lembre-se de usá-lo apenas na depuração, ou então seu aplicativo será rejeitado.

Enzo Tran
fonte
6
Parece que este código simula com precisão o aviso de memória no dispositivo. Obrigado Enzo!
William Denniss
28
Em vez de usar isso no código, execute-o no depurador. Basta clicar em pausa e entrarpo [[UIApplication sharedApplication]performSelector:@selector(_performMemoryWarning)]
orkoden
17
Ao invés de usar po, expr utilização, isto é,expr (void)[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];
Andy
11
No depurador, você não precisa usar a solução alternativa para não ter o cabeçalho:expr (void)[[UIApplication sharedApplication] _performMemoryWarning]
OrangeDog
3
Para quem está procurando fazer isso com o Swift: digite em expr UIApplication.sharedApplication().performSelector("_performMemoryWarning")vez de usar o normal#selector
funct7 de
27

O Simulate Memory Warningitem de menu do simulador iOS permite simular um aviso de memória.

Ole Begemann
fonte
A única maneira de verificar no dispositivo é realmente forçá-lo, ou seja, usando o aplicativo por longos períodos de tempo ou imagens intensas ou o que quer que seja, irá variar de aplicativo para aplicativo. Uma sugestão pode ser usar um dispositivo mais antigo (3g talvez?) Em vez de um iPhone 4 para ajudá-lo a obter o aviso mais rapidamente.
Jesse Naugher
Obrigado, Jesse, acho que vou apenas adicionar alguns hacks ao meu aplicativo para simular convites para que eu possa executá-lo no simulador e induzir os avisos de memória dessa forma.
BeachRunnerFred
10
A pergunta era sobre a simulação no dispositivo.
KPM
20

Usando instrumentos, use o item de menu: Instrumento -> Simular Aviso de Memória.

Para usar instrumentos em seu aplicativo do Xcode, use o item de menu Produto -> Perfil.

ThomasW
fonte
Isso é ainda melhor.
Zappel de
@OrangeDog O que está acontecendo?
ThomasW
2
Bem, nada. Quando eu uso as visualizações de resposta do Enzo, tenho que recarregar quando eu volto a elas, não usando esse método.
OrangeDog
12

Eu re-escrito a resposta de Enzo Tran em Swift:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)
ChikabuZ
fonte
Obrigado! O Xcode avisa sobre "nenhum método declarado com o seletor Objective-C", mas isso funciona mesmo assim.
man1
10

Se alguém, por qualquer motivo, tentar fazer isso no Swift 4 - aqui está como alocar 1,2 GB de RAM.

let d = Data.init(repeating: 100, count: 1200000000)
  • Isso é útil para acionar um alerta de aviso em outros aplicativos
Adobels
fonte
Será que fazer algo assim ofuscará as informações reais da memória que estou tentando visualizar em Instrumentos? Embora eu veja que não há uma maneira adequada de fazer isso em um dispositivo físico, se meu objetivo é ver o que está ocupando minha memória no meu aplicativo, parece que isso vai distorcer todos os dados e não já tem uma resposta relativa. Ainda verei o que está ocupando mais , mas não as verdadeiras proporções.
Jake T.
isso trava imediatamente
Daniel Springer
7

Há um comando de menu que o chamará.

Hardware > Simulate Memory Warning do simulador.

Daniel A. White
fonte
8
A pergunta era sobre a simulação no dispositivo.
KPM
2
No Xcode 10 está agora sob o aviso Debug> Simulate Memory.
Sebbo
7

@ChikabuZ convertido para swift 3:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)
meio que
fonte
4

Se alguém, por qualquer motivo, tentar fazer isso no Swift 3 - aqui está como alocar 1,2 GB 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
fonte
3
let d = Data.init (repetindo: 100, contagem: 1200000000)
Adobels
2
@Adobels você deve postar isso como uma resposta :)
Koen.
1

Swift 4:

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

Pode executar o acima em resposta a um evento / notificação.

Vishal Chaudhry
fonte