Надежное принудительное завершение фонового приложения из-за нехватки памяти
Я пытаюсь понять условия, которые приводят к тому, что система iOS перезапускает приложение, которое было остановлено из-за нехватки памяти. Создание достаточного давления памяти было трудно, хотя.
В настоящее время мой подход состоит в том, чтобы запустить мое приложение через XCode, фоновый режим и запустить вспомогательное приложение, которое потребляет память. Он выделяет биты памяти в цикле NSTimer, пока система iOS не убьет его. Когда мне везет, Xcode сообщает мне, что мое основное приложение было "закрыто из-за давления памяти".
Я ищу более надежный способ добиться этого. Существуют ли методы выделения памяти или частные API, которые лучше для этой цели?
2 ответа
Я немного удивлен поведением, которое вы описываете, но несколько мыслей:
Насколько я знаю, iOS не дает никаких гарантий относительно порядка, в котором приложения отбрасываются, и не гарантирует, что все фоновые приложения будут отброшены (или будет ли она просто пытаться выбросить достаточно приложений, чтобы уменьшить состояние нагрузки на память). Обработка нехватки памяти в iOS и Mavericks предлагает некоторые подсказки, но я не могу ручаться за это. Но ОС использует некоторую сложную логику, поэтому я не решусь делать какие-либо твердые заявления о шагах, которые необходимо предпринять, чтобы гарантировать, что конкретное приложение будет отброшено.
Эта проблема порядка удаления фоновых приложений будет зависеть от того факта, что вы разрешаете аварийное завершение приложения. Вполне возможно, что фоновые приложения могут быть отброшены недостаточно быстро, чтобы удовлетворить попытки выделения вашего вспомогательного приложения. Таким образом, приложение-помощник может зависнуть до того, как iOS откажется от запуска вашего основного приложения.
Я мог бы предложить немного другой дизайн вспомогательного приложения, так что, когда оно получает предупреждение о памяти, оно освобождает всю запрошенную память и запускает процесс снова. В моем приложении "Cause Memory Pressure" я фактически жду несколько секунд между остановкой выделений, когда получаю предупреждение о памяти, и процессом перезапуска выделений.
Но, суть в том, что вы, возможно, захотите убедиться, что вспомогательное приложение не аварийно завершится, чтобы убедиться, что вы полностью задействуете системы сжатия памяти.
Вы описываете ожидание отладчика в XCode, чтобы сообщить, что приложение прекращено. Я мог бы предложить повторить ваш эксперимент, запустив основное приложение непосредственно на устройстве, но не через отладчик. Я предлагаю это, потому что мне кажется теоретически возможным, что тот факт, что ваше приложение подключено к отладчику, на самом деле может повлиять на вычисление приоритета при определении того, какие приложения должны быть отброшены.
Поскольку приложение будет убито, нет смысла запускать его через отладчик в любом случае, потому что, если ОС делает что-то для перезапуска приложения (например, фоновый режим)
NSURLSession
, push-уведомление и т. д.), ваш сеанс отладки в любом случае исчезнет. Так что нет смысла запускать его через отладчик, чтобы наблюдать вопрос "что, если ОС перезапустит мое приложение".Лично, при диагностике поведения приложений, которые были отброшены, перезапущены и т. Д., Я использую Организатор устройства Xcode и наблюдаю там за Консолью устройства. Вы можете наблюдать за любым оператором NSLog вашего приложения в консоли, а также наблюдать, как приложения отбрасываются, ваше приложение перезапускается (если операционная система действительно что-то делает для его перезапуска) и т. Д.
Я предполагаю, что вы хотите выполнить тестирование, правильно ли вы сохранили состояние, поэтому при повторном запуске вы вернетесь туда, где вы были.
Я бы посоветовал установить флаг, чтобы, когда ваше приложение обнаружило, что оно было перемещено в фоновый режим (applicationDidEnterBackground:), оно запрашивает больше времени, выполняет все изменения состояния, а затем либо находится в цикле вращения, либо убито. или выполняет `exit(0)'. Вы должны увидеть, что приложение "умерло" в XCode, и затем вы можете перезапустить его.