Как выполнить локальное резервное копирование, если приложение iOS закрыто?
Моя цель такова: выполнить локальное резервное копирование/копирование некоторых файлов/папок.
Мое приложение представляет собой форк приложения Signal с открытым исходным кодом от GitHub. приложение для обмена сообщениями. Сообщения хранятся в локальной базе данных.
- Мне нужно выполнять локальное резервное копирование в моем приложении iOS, по крайней мере, один раз в день, даже если приложение не работает в фоновом режиме, а закрыто.
- Никакой сервер не участвует в резервном копировании, все это локальный процесс, в котором некоторые файлы, такие изображения и базы данных необходимо скопировать в папку, заархивировать и зашифровать.
- Никакого оповещения от пользователя не требуется.
- Приложения не будет в магазине, поэтому у меня нет страха перед обзором в данный момент.
Я нашел только ссылки на фоновую активность со схемой фоновой задачи (не обновления), о которой я сообщаю в этом вопросе, но она будет работать в соответствии с потребностями и желаниями ОС, даже если был установлен предпочтительный час. Это я поняла. Я привожу свой код для примера и возможную помощь.
Но можно ли выполнять интенсивную операцию резервного копирования, пока приложение закрыто? Есть ли способ выполнять локальное резервное копирование хотя бы раз в день, даже если приложение закрыто? как работают другие приложения, такие как «Календарь», «Будильник»?
Итак, никаких ярлыков, мне нужно понять, есть ли какой-нибудь способ забронировать задачу, пока приложение закрыто или, по крайней мере, приостановлено. Если ответ «невозможно», ничего страшного, мне просто нужна ссылка на объяснение моей компании.
Это мой код для фоновой задачи. Если невозможно выполнить то, что я прошу, правильный ли этот код? Попробовал проверить на консоли, вроде работает.
Ориентирован как минимум на iOS 13 с использованием UIKit.
Я включил фоновые режимы, фоновую выборку и фоновую обработку в настройках и возможностях, затем добавил строку для BGProcessingTaskRequest.
ОБНОВЛЕНО с BGAppRefreshTask на BGProcessingTaskRequest (нет ограничения активности в 30 секунд).
import UIKit
import BackgroundTasks
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.mytask", using: nil) { task in
self.handleAppRefreshTask(task: task as! BGProcessingTaskRequest)
}
scheduleAppRefresh()
return true
}
func scheduleAppRefresh() {
print("called: scheduleAppRefresh")
let request = BGProcessingTaskRequest(identifier: "com.example.mytask")
request.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("not possible scheduling background app activity: \(error.localizedDescription)")
}
}
func handleAppRefreshTask(task: BGProcessingTaskRequest) {
let startDate = Date()
print("starting backup date: \(startDate)")
DispatchQueue.global().async {
let backupDuration: TimeInterval = 180
let endTime = Date(timeIntervalSinceNow: backupDuration)
while Date() < endTime {
print("performing backup...")
Thread.sleep(forTimeInterval: 1)
}
let endDate = Date()
print("end of backup: \(endDate)")
task.setTaskCompleted(success: true)
}
scheduleAppRefresh()
}
}
моя информация.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.example.mytask</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
</array>
</dict>
</plist>
1 ответ
Вам нужен инструмент BGProcessingTaskRequest , и это именно тот вариант использования, для которого он предназначен, но его не обещают запускать один раз в день. Не существует механизма запуска чего-либо по определенному расписанию, кроме отправки тихих push-уведомлений, которые имеют различные собственные ограничения (например, пользователь может их отключить, а телефону требуется подключение к сети или сотовой сети). Не существует гарантированного способа запуска кода по фиксированному расписанию. Это сделано специально. Попытка обойти это с помощью таких трюков, как фоновый звук, как вы предлагаете, плоха и может привести к тому, что вы не пройдете проверку приложения и будете удалены из магазина.
Вам следует сделать шаг назад и подумать о реальной проблеме, которую вы пытаетесь решить. Поскольку сервера нет, похоже, что на самом деле это не «резервное копирование», а скорее перемещение/копирование чего-либо в файлы ежедневного использования. Если вы это делаете, вы можете сделать это при запуске приложения; вам не обязательно делать это именно тогда, когда меняется день. И вы можете использовать BGProcessingTaskRequest, чтобы запланировать это «время от времени» в фоновом режиме, чтобы это не сильно влияло на время запуска.