Обновление приложения WatchKit с радиомаяком

Я работаю над созданием iOS-приложения Swift, которое включает iBeacons для предоставления данных в приложение WatchKit (OS 1). Приложение загружает данные из JSON в tableView на основе того, установлен ли маяк CLProximity на .Near или .Immediate. Приложение iOS при запуске может обнаруживать маяки без проблем, заполнять переменную и делать ее доступной для приложения WatchKit. Однако, когда приложение WatchKit пытается запросить данные маяка из приложения с помощью application:handleWatchKitExtensionRequest, когда iOS не был запущен первым, объект для маяков возвращается как nil. Мое предположение заключается в том, что когда приложение закрыто на телефоне, вызов WatchKit для открытия родительского приложения НЕ запускает код ранжирования маяка, который хранится в AppDelegate. Перемещение кода инициализации маяка в application:handleWatchKitExtensionRequest не устраняет проблему.

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

  • Пользователь приложения запускает приложение-наблюдатель для проверки данных поблизости.
  • Приложение watch запрашивает список ближайших/ближайших маяков из приложения iOS.
  • Приложение iOS возвращает список маяков Основные строки для маяков, которые соответствуют этим критериям.
  • Оптимально приложение iOS позволяет Наблюдающему приложению узнать, когда этот список изменится, и приложение WatchKit обновится.

У меня такое чувство, что часть моего решения лежит в DarwinNotification и с регистрацией наблюдателей, которые не являются тем, с чем я работал много раньше, но примеров StackOverflow достаточно, что я могу их реализовать, если это так, Я предполагаю, что реальная проблема заключается в том, как собирать данные маякового радиосигнала, когда приложение iOS еще не запущено.

Ответ 1

Перемещение кода на application:handleWatchKitExtensionRequest только частично решает проблему; Основная проблема заключается в том, что ваш маяк не готов немедленно (CLLocationManager - очень асинхронный компонент), и поэтому требуется действительно получить необходимую информацию.

Я лично работал над чем-то похожим, как мой забавный проект - на самом деле это был видеопроигрыватель для Watch OS1 (у которого нет функций проигрывателя), и мне это удалось. Таким образом, модель WK1 действительно проста - вы запрашиваете приложение, вы получаете возможность ответить в

  func application(application: UIApplication, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]?, reply: (([NSObject : AnyObject]!) -> Void)!)

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

Итак, что вы могли бы сделать, по моему мнению, следующее:

  • В приложении watch запросите данные маяка
  • В вашем приложении проверьте наличие маяковых данных
  • Если у вас есть они, просто представьте их в WKInterfaceTable или, тем не менее, вы это сделаете
  • Если вы этого не сделаете, запросите beacon, сохраните закрытие ответа
  • После получения данных от маяка вызовите замыкание так же, как и в (3)

Может возникнуть одна проблема: приложение будет разорвано, прежде чем вы получите ответ. В этом случае последующие вызовы должны позаботиться о том, чтобы

UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({})

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

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

Если у вас есть дополнительные вопросы или есть проблема с этим решением, просто спросите, и мы это выясним!:) Удачи!

Edit:

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

Ответ 2

Если это помогает, на странице "Советы Apple WatchKit" предлагается:

"Приложение iPhone должно выполнить большую часть работы. Если ваше приложение на Apple Watch необходимо выполнять более длительные фоновые задачи, такие как создание сетей звоните, вы должны полагаться на свое приложение для iPhone, чтобы выполнить эту работу. Использовать openParentApplication: reply: метод в WKInterfaceController для пробуждения закройте приложение iPhone в фоновом режиме и верните данные, которые Требуется расширение WatchKit. Метод UIApplicationDelegate, который обрабатывает запрос WatchKit, должен немедленно вернуться. Если требуется асинхронный вызов, например, для работы в сети, используйте фоновая задача, чтобы убедиться, что ваше приложение не приостановлено до того, как оно шанс отправить ответ".

Проверьте это, а связанные документы - https://developer.apple.com/watchkit/tips/