Разработка под iOS: как я могу вызвать предупреждения о нехватке памяти на устройстве?

93

Я хотел бы хорошо протестировать работу моего приложения в условиях нехватки памяти, но это сложно проверить. Как я могу вызвать предупреждения о нехватке памяти, которые запускают метод didReceiveMemoryWarning в моих представлениях, когда приложение работает на устройстве, а не в симуляторе? Или как я могу протестировать свое приложение в этих возможных условиях?

Причина, по которой я не могу использовать симулятор, заключается в том, что мое приложение использует Game Center, а приглашения не работают на симуляторе.

BeachRunnerФред
источник

Ответы:

9

Чтобы протестировать устройство, просто добавьте код, который периодически выделяет большие фрагменты памяти, не освобождая их (т.е. утечка намеренно). Вы можете сделать это в отдельном потоке или в ответ на таймер, или с помощью любого механизма, который лучше всего позволяет вам тестировать и наблюдать за поведением вашего приложения.

Вы также можете создать отдельное приложение, которое делает что-то подобное и предназначено для работы в фоновом режиме, если вы хотите легко повторно использовать это и / или протестировать с несколькими приложениями.

BinaryStar
источник
7
не очень практично. решение вызвать частный метод для тестирования лучше
Дайдж-Джан
5
Не лучшее решение, если вы хотите взглянуть на сценарий реального мира. Вы нарушаете работу приложения из-за утечки, а не из-за нехватки памяти. Это плохо, так как вы хотите проверить, как приложение реагирует в состоянии высокой нагрузки на память. С другой стороны, сложнее понять, в чем проблема - настоящая утечка или поддельная, которую вы внесли. Для тестирования лучше использовать частный метод, как указано ниже.
fzaziz
2
Этот ответ не следует отвергать, поскольку второй абзац на самом деле является тем, что Apple говорит делать, если вы хотите протестировать поведение своего приложения, когда памяти действительно мало.
Мэтт
1
Ответ будет улучшен с помощью блока кода для выполнения этого распределения!
pkamb
Хотя для настройки требуется больше работы, это более реалистичный тест, чем вызов частного метода. Когда действительно критическая нагрузка на память, сможет ли ваше приложение выполнять действия, которые вы ему приказываете? И улучшат ли эти действия ситуацию или ухудшат ее и заставят iOS ее прекратить? Кроме того, закрытый метод не работает для тестирования DISPATCH_SOURCE_TYPE_MEMORYPRESSURE.
jk7
278

Вы можете вызвать частный метод :

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

Просто не забудьте использовать его только для отладки, иначе ваше приложение будет отклонено.

Энцо Тран
источник
6
Похоже, этот код точно имитирует предупреждение о памяти на устройстве. Спасибо, Энцо!
Уильям Деннисс,
28
Вместо того, чтобы использовать это в коде, выполните его в отладчике. Просто нажмите паузу и введитеpo [[UIApplication sharedApplication]performSelector:@selector(_performMemoryWarning)]
orkoden
17
Вместо того, чтобы использовать po, используйте expr, то естьexpr (void)[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];
Энди
11
В отладчике вам не нужно использовать обходной путь, если у вас нет заголовка:expr (void)[[UIApplication sharedApplication] _performMemoryWarning]
OrangeDog,
3
Для тех, кто хочет сделать это с помощью Swift: введите expr UIApplication.sharedApplication().performSelector("_performMemoryWarning")вместо обычного#selector
funct7
30

Simulate Memory WarningПункт меню iOS Simulator позволяет имитировать предупреждение о памяти.

Оле Бегеманн
источник
Единственный способ проверить это на устройстве - это заставить его, то есть использовать приложение в течение длительных периодов времени или использовать интенсивные изображения или что-то еще, будет варьироваться от приложения к приложению. Может быть предложено использовать более старое устройство (возможно, 3G?) Вместо iPhone 4, чтобы помочь вам быстрее добраться до предупреждения.
Джесси Ногер
Спасибо, Джесси, думаю, я просто добавлю несколько хаков в свое приложение для имитации приглашений, чтобы я мог запустить его в симуляторе и таким образом вызвать предупреждения памяти.
BeachRunnerFred
10
Вопрос касался моделирования на устройстве.
KPM
20

Используя инструменты, используйте пункт меню: Instrument -> Simulate Memory Warning.

Чтобы использовать инструменты в своем приложении из Xcode, используйте пункт меню Продукт -> Профиль.

ThomasW
источник
Это даже лучше.
Zappel,
@OrangeDog Что происходит?
ThomasW
2
Ну ничего. Когда я использую Enzo, представления ответов должны перезагружаться, когда я возвращаюсь к ним, а не при использовании этого метода.
OrangeDog
12

Я переписал ответ Энцо Тран на Swift:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)
ЧикабуЗ
источник
Благодарность! Xcode предупреждает о том, что с селектором Objective-C не объявлен метод, но, тем не менее, это работает.
man1
10

Если кто-то по какой-то причине попытается сделать это в Swift 4 - вот как выделить 1,2 ГБ оперативной памяти.

let d = Data.init(repeating: 100, count: 1200000000)
  • Это помогает вызвать предупреждение в других приложениях.
Блажей СЛЕБОДА
источник
Будет ли что-то подобное запутать фактическую информацию о памяти, которую я пытаюсь просмотреть в инструментах? Хотя я вижу, что на физическом устройстве нет правильного способа сделать это, если я хочу посмотреть, что занимает мою память в моем приложении, похоже, что это исказит все данные, и я не буду уже есть относительный ответ. Я все равно посмотрю, что занимает больше , но не в истинных пропорциях.
Джейк Т.
это немедленно вылетает
Дэниел Спрингер,
8

Преобразовал @ChikabuZ в быстрый 3:

UIControl().sendAction(Selector(("_performMemoryWarning")), to: UIApplication.shared, for: nil)
своего рода
источник
7

Есть команда меню, которая ее вызовет.

Hardware > Simulate Memory Warning из симулятора.

Дэниел А. Уайт
источник
8
Вопрос касался моделирования на устройстве.
KPM
2
В Xcode 10 он теперь находится в разделе «Отладка»> «Имитация памяти».
Sebbo
4

Если кто-то по какой-то причине попытается сделать это в Swift 3 - вот как выделить 1,2 ГБ оперативной памяти.

   for i in 0...1200 {
      var p: [UnsafeMutableRawPointer] = []
      var allocatedMB = 0
      p.append(malloc(1048576))
      memset(p[allocatedMB], 0, 1048576);
      allocatedMB += 1;
   }
ph1lb4
источник
3
let d = Data.init (повторяется: 100, count: 1200000000)
Blazej SLEBODA
2
@Adobels, ты должен опубликовать это как ответ :)
Коэн.
1

Swift 4:

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

Может выполнить вышеуказанное в ответ на событие / уведомление.

Вишал Чаудри
источник