#swift #core-data #swiftui #cloudkit #widgetkit
#swift #основные данные #swiftui #cloudkit #widgetkit
Вопрос:
У меня есть приложение, которое использует основные данные с CloudKit. Изменения синхронизируются между устройствами. Основной целевой объект имеет возможность фоновых режимов с проверкой Remote notifications
, возможность iCloud проверяется с помощью служб, настроенных на CloudKit, и правильного контейнера в контейнерах.
Как я могу реагировать в коде на изменения, удаление и добавление записей? Мне нужно позвонить WidgetCenter.shared.reloadAllTimelines()
, когда основные данные в CloudKit изменятся, чтобы обновить виджет рабочего стола iOS 14.
Моя цель — заставить это работать: я изменяю / добавляю / удаляю запись в icloud.developer.apple.com или другое устройство, и WidgetCenter.shared.reloadAllTimelines()
вызывается для отображения правильных данных в виджете. Приложение может находиться в фоновом режиме или на переднем плане.
От AppDelegate.swift
:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Register for Remote Notifications
application.registerForRemoteNotifications()
return true
}
Кроме того, замеченные сообщения в журнале вывода:
CoreData: debug: CoreData CloudKit: -[NSCloudKitMirroringDelegate remoteStoreDidChange:]_block_invoke(2138): <NSCloudKitMirroringDelegate: 0x281818d00> — Игнорирование уведомления об удаленных изменениях, поскольку экспортер уже перехватил эту транзакцию: 64/64 — < NSSQLCore: 0x100b09440> (URL: файл:///var/мобильный/Containers/Data/Application/F83C68DA-7C36-42CC-926D-7C721C679579/Library/Application Support/AppTitle.sqlite)
Ответ №1:
Если вы хотите подписаться на удаленные уведомления Core Data, вы можете использовать onReceive
:
struct WidgetEntryView : View {
var entry: Provider.Entry
var body: some View {
Text(entry.date, style: .time)
.onReceive(NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange)) { _ in
// make sure you don't call this too often
WidgetCenter.shared.reloadAllTimelines()
}
}
}
Просто убедитесь, что вы не вызываете reloadAllTimelines()
слишком часто — вероятно, для вашего виджета доступно ограниченное количество обновлений.
Комментарии:
1. Вы действительно уверены, что это будет работать так, как задумано? Насколько я понимаю, как только виджет завершает возврат временной шкалы
getTimeline
, расширение виджета прекращается. Таким образом, этот прослушиватель сможет прослушивать только в течение нескольких секунд жизни расширения. Из того, что я прочитал в документах, такое прослушивание может быть выполнено только из приложения: developer.apple.com/documentation/widgetkit /. … Видя, что за это проголосовали, кому-нибудь действительно удалось заставить это работать надежно?2. Я также подозреваю, что это не будет работать как есть. Я думаю, что если бы у вас был этот код в вашем основном приложении, он бы работал. И пока приложение находится на переднем плане, нет ограничений на количество вызовов
reloadAllTimelines()
(конечно, вы хотите, чтобы это работало и в фоновом режиме, но просто уточняю)