Уменьшение объема памяти для обеспечения работы в фоновом режиме в iOS

При разработке приложения, использующего Bluetooth Low Energy, наступает момент, когда устройство iOS теряет соединение с периферийным устройством. (Иногда часами.)

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

Проблема в том, что iOS не гарантирует, что ваше приложение не будет уничтожено из-за нехватки памяти и т. д.

Информация в Руководстве по программированию для iPhone OS говорится, что:

Приложения, работающие с периферийными устройствами Bluetooth, могут запросить пробуждение, если периферийное устройство доставляет обновление, когда приложение приостановлено. Эта поддержка важна для аксессуаров Bluetooth-le, которые передают данные через регулярные промежутки времени, таких как пульсометр Bluetooth. Когда приложение включает ключ UIBackgroundModes со значением bluetooth-central в свой файл Info.plist, платформа Core Bluetooth сохраняет открытыми все активные сеансы для соответствующего периферийного устройства. Кроме того, новые данные, поступающие с периферийного устройства, заставляют систему активировать приложение, чтобы оно могло обработать данные. Система также активирует приложение для обработки уведомлений о подключении и отключении аксессуара.

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

Многие люди обсуждали это раньше либо на Stack Overflow, либо на форумах Apple, и я полагаю, что один из разработчиков Apple ответил, сказав:

Мы знаем об этой проблеме и пытаемся найти решение. В настоящее время обходного пути нет».

Мой вопрос: есть ли способ хотя бы повысить ваши шансы не быть убитым iOS из-за нехватки памяти?

Например, приложение для обмена мгновенными сообщениями (IMO), кажется, довольно хорошо работает в фоновом режиме. Через несколько дней бездействия приложение проснется и отобразит сообщение gChat.

Я ставлю под сомнение такие вещи, как

  • Сильные указатели
  • Общий объем памяти
  • Уменьшение размера памяти, когда приложение находится в фоновом режиме или свернуто
  • Уменьшение частоты фоновой работы
  • И Т. Д.

person Jonathan    schedule 07.01.2013    source источник


Ответы (3)


Зачем вам нужно фоновое выполнение, даже когда оборудование Bluetooth отключено? Я не думаю, что вам нужно «непрерывно повторно сканировать», чтобы снова подключиться, если оборудование «сопряжено» с iPhone / iPad, оно само подключится. Как блютуз гарнитура. Или нет?

Насколько я знаю, у вас нет шансов выполнить то, о чем вы просите. Обычное приложение всегда приостанавливается, когда пользователь возвращается домой. Приложение имеет ок. 5 секунд фонового времени для остановки таймеров, сохранения состояния ecc ecc. Существуют специальные фоновые режимы, которые позволяют вам иметь больше фонового времени, и каждый из этих режимов (объясненный на странице, на которую вы ссылаетесь) имеет различное поведение.

О режиме bluetooth: описанное поведение не является проблемой, но так задумано:

  • приложение приостановлено

  • когда приложение приостановлено, ОС может убить его, чтобы освободить оперативную память (и нет способов избежать этого), но при необходимости система проснется.

  • затем приложение пробуждается каждый раз при получении уведомления (пробуждение из приостановленного состояния или запуск из состояния «ранее убитого»)

  • у приложения есть 10 секунд для выполнения задач (сохранение информации, и т. д. и т. д.). Кроме того, можно запросить +10 мин. фонового времени для конкретной задачи

  • через 10 секунд (или 10 минут) приложение снова приостанавливается

Пример, который вы написали о приложении чата, неверен: приложения чата обычно не используют какой-либо фоновый режим, они просто пересылают вам сообщения с помощью push-уведомлений. Когда вы открываете приложение, оно подключается к серверу, на котором хранятся все ваши сообщения, и загружает его.

Вы можете получить «больше времени безотказной работы», используя фоновый режим местоположения (приложение маршрутизации может работать в фоновом режиме) или используя комбинацию значительных изменений местоположения (приложение пробуждается) и 10-минутное фоновое время, но я думаю, что Apple отклонит приложение что "злоупотребляют" этим.

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

person LombaX    schedule 07.01.2013
comment
BLE действует иначе, чем сопряженное устройство BT2.1. Вам нужно просканировать рекламные пакеты, а затем установить соединение. Мне нужно было бы сделать это, если бы я был отключен от устройства в течение значительного времени, а затем вошел в его диапазон близости. В этот момент сканирование нашло бы рекламные пакеты устройства, и оно снова подключилось бы. Если само приложение было убито, то фоновое сканирование не будет происходить, и оно будет повторно подключаться только в том случае, если вы откроете приложение. - person Jonathan; 07.01.2013
comment
@shred444: «BLE действует иначе, чем сопряженное устройство BT2.1. Вам нужно просканировать рекламные пакеты, а затем установить соединение». Из того, что я знаю об iOS, идея о том, что фоновое приложение может быть уничтожено в любое время, довольно фундаментальна. Я ожидаю, что Apple решит эту проблему, заставив iOS самостоятельно сканировать рекламные пакеты, а затем сообщать приложениям, когда находит их. (Судя по вашему вопросу, я предполагаю, что они еще не реализовали ничего подобного для Bluetooth Low Energy.) - person Paul D. Waite; 07.01.2013
comment
Я согласен. В списке рассылки Core Bluetooth Apple Dev один из разработчиков упомянул: «Мы знаем об этой проблеме и пытаемся найти решение. В настоящее время обходного пути нет. Так что, надеюсь, они реализуют что-то похожее на то, что вы описываете. До тех пор похоже, что сокращение сильных ссылок поможет улучшить продолжительность фона (см. Мой ответ ниже) - person Jonathan; 07.01.2013
comment
@shred444, даже если приложение не убито, как бы вы начали сканирование, если оно не запущено? Состояния приложения: запущено (не в этом случае), фоновая задача (максимум 10 минут), приостановлено, остановлено (убито/закрыто). Если приложение не находится в убитом состоянии и не находится в 10-минутном режиме фоновой задачи, оно приостановлено --> вы не можете запустить какую-либо задачу в приостановленном состоянии. Приостановленное состояние может быть остановлено только пользователем или iOS, пробуждающим приложение. - person LombaX; 08.01.2013
comment
Что касается других комментариев, я не знал этой детали о низком энергопотреблении Bluetooth, я подтверждаю, что (насколько мне известно) сейчас нет шансов, поэтому нужно ждать патча от Apple :-( - person LombaX; 08.01.2013
comment
Я нашел этот пост: lists.apple.com/archives/bluetooth -dev/2011/Dec/msg00007.html говорит: вызов scanForPeripheralsWithServices или connectPeripheral будет продолжаться, даже если приложение находится в фоновом режиме. CoreBluetooth будет продолжать отслеживать определенные периферийные устройства или периферийные устройства, которые соответствуют службам, которые ищет ваше приложение, и вызывать вашего делегата приложений при обнаружении или подключении. Насколько мне известно, это означает, что он работает, даже если приложение убито (система запускает приложение снова, если некоторые события должны обрабатываться приложением) - person LombaX; 08.01.2013

Я нашел это в другой документации Apple:

Использование памяти фоновыми приложениями

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

С практической точки зрения ваше приложение должно удалять сильные ссылки на объекты, как только они больше не нужны. Удаление сильных ссылок дает компилятору возможность сразу освобождать объекты, чтобы можно было освободить соответствующую память. Однако если вы хотите кэшировать некоторые объекты для повышения производительности, вы можете подождать, пока приложение перейдет в фоновый режим, прежде чем удалять ссылки на них.

Вот некоторые примеры объектов, на которые следует как можно скорее удалить сильные ссылки:

Объекты изображения

Большие мультимедийные файлы или файлы данных, которые вы можете снова загрузить с диска. Любые другие объекты, которые не нужны вашему приложению и могут быть легко воссозданы позже. на задний план.

Система очищает резервное хранилище для всех слоев Core Animation. Это усилие не удаляет объекты слоя вашего приложения из памяти и не изменяет свойства текущего слоя. Это просто предотвращает появление содержимого этих слоев на экране, что, учитывая, что приложение находится в фоновом режиме, в любом случае не должно происходить. Он удаляет любые системные ссылки на кешированные изображения. (Если ваше приложение не имеет сильной ссылки на изображения, они впоследствии удаляются из памяти.) Оно удаляет сильные ссылки на некоторые другие кэши данных, управляемые системой.

person Jonathan    schedule 07.01.2013
comment
Вы можете резюмировать это в нескольких словах: если вы хотите иметь больше шансов, что приложение не будет убито iOS во время приостановки, сделайте его объем памяти как можно меньше. Просто чтобы было ясно, сокращение сильных ссылок не означает, что вам нужно избегать сильных ссылок в переменных экземпляра, вам просто нужно обнулить как можно больше переменных экземпляра, прежде чем приложение перейдет в фоновый режим. (так что память, на которую ссылаются эти переменные, не имеет более сильных ссылок --> память может быть освобождена) - person LombaX; 08.01.2013
comment
(но, смотрите мои другие комментарии, это, к сожалению, вам не поможет :-() - person LombaX; 08.01.2013

Из документации Apple я всегда предполагал следующее:

connectPeripheral:options:
Establish a connection to the peripheral.

- (void)connectPeripheral:(CBPeripheral *)peripheral options:(NSDictionary *)options;
Parameters
peripheral
The peripheral to connect to.

options
A dictionary to customize the behavior of the connection. See CBConnectPeripheralOptionNotifyOnDisconnectionKey.

Discussion
**This never times out**. Use cancelPeripheralConnection: to cancel a pending connection.'

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

person Martin    schedule 08.01.2013
comment
Это никогда не истекает в отношении приложения переднего плана. У iOS нет проблем с уничтожением всего приложения, включая процесс сканирования, когда оно работает в фоновом режиме. - person Jonathan; 08.01.2013
comment
Можете ли вы опубликовать ссылку или код, показывающий проблему? Как указано в другой ссылке (lists.apple.com/archives/ bluetooth-dev/2011/Dec/msg00007.html) и в документации методы scanForPeripheralsWithServices: и connectPeripheral: управляются CoreBluetooth, а не приложением, так что это не проблема, если приложение будет убито --› он будет разбужен, когда это необходимо, но сканирование продолжится (им управляет iOs, а не приложение). Важно: какое устройство вы используете? BLE поддерживается только более новыми устройствами (iPhone 4S — iPhone 5). Посмотрите на этот другой пост: tmblr.co/Z0DVRya_lcSH - person LombaX; 08.01.2013