Как правильно реализовать перенос настроек из приложения iOS в услугу watchOS2
Я хочу добиться следующего:
- Осложнения обновляются в фоновом режиме с интервалом в 30 минут
- Осложнения обновляются всякий раз, когда приложение для часов запускает и получает собственные обновленные данные.
- Сложности обновляются всякий раз, когда приложение iOS запускается, и пользователь изменяет настройку, которая влияет на данные наблюдения (например, изменение местоположения наблюдений за погодой или единиц отображения)
Пункты 1. и 2. кажутся простыми и хорошо рассмотрены здесь: Каков порядок обновления данных об осложнениях для Apple Watch?
Однако для пункта 3 в приложении для iOS я настроил экземпляр WCSession и вызвал TransferCurrentComplicationUserInfo, отправив новые настройки как NSDictionary. В расширении наблюдения это вызывает didReceiveUserInfo в WCSessionDelegate.
- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *,id> *)userInfo {
// Code here to apply the new settings
// ....
// Invoke a NSUSRLSession-based web query to get new data
[self queryForNewDataWithCompletionHandler:^(NCUpdateResult result) {
if (result == NCUpdateResultNewData) {
// Have new data from web to display
CLKComplicationServer *server = [CLKComplicationServer sharedInstance];
for (CLKComplication *complication in server.activeComplications) {
[server reloadTimelineForComplication:complication];
}
}
// Set date for next complication update to 30 mins from now
// ...
}];
}
Проблема, с которой я сталкиваюсь, заключается в том, что watchOS вызывает требуемый UpdateDidBegin в отдельном потоке, вскоре после того, как он вызвал didReceiveUserInfo, и это начинает выполняться ДО того, как у меня появится возможность получить обновленные данные, используя новые настройки в недавно полученном словаре UserInfo из приложения.
Следовательно, сложности обновляются два раза подряд - один раз, когда WatchOS вызвал requestUpdateDidBegin, который просто обновляет сложность с существующими (устаревшими) данными, прежде чем я очень скоро получу новые данные из Интернета, а затем должен будет их обновить. снова в моем собственном коде.
Это кажется ненужным и пустой тратой ресурсов, не говоря уже об ограниченном бюджете обновлений, которые Apple разрешает (предположительно 2 в час).
Я что-то здесь не так делаю? Как я могу запретить watchOS2 вызывать requestUpdateDidBegin до того, как у меня появится возможность получить новые данные из Интернета?
1 ответ
Цель transferCurrentComplicationUserInfo
это немедленно передать текущие данные о сложности на расширение. В вашем коде вы передаете настройки, однако вы не включаете никаких погодных данных.
Проблема, с которой вы столкнулись, связана с попыткой асинхронной выборки новых данных в расширении (которое возвращается до того, как эти данные станут доступны).
Чтобы справиться с этим, вы должны получить текущие данные о погоде на телефоне, основанные на новых настройках, а затем передать (новые настройки вместе с) данные о погоде в текущей информации о пользователе сложности.
- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *,id> *)userInfo {
// Code here to apply the new settings for future updates
// ....
// Code here to update cache/backing store with current weather data just passed to us
// ....
CLKComplicationServer *server = [CLKComplicationServer sharedInstance];
for (CLKComplication *complication in server.activeComplications) {
[server reloadTimelineForComplication:complication];
}
}
Таким образом, сервер усложнения может немедленно обновить временную шкалу, используя текущие данные о сложностях, которые вы только что передали в часы.
Нет устаревших данных, нет ненужного второго обновления.