mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-26 21:39:37 -04:00
Pausing task when app quits
This commit is contained in:
parent
e5f5cb4909
commit
aa60ae8919
@ -89,7 +89,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
URLProtocol.registerClass(KiwixURLProtocol.self)
|
||||
|
||||
// Network.shared
|
||||
Network.shared
|
||||
|
||||
// Register notification
|
||||
if let _ = Preference.libraryLastRefreshTime { registerNotification() }
|
||||
|
@ -59,10 +59,26 @@ class LibraryDownloadController: CoreDataTableBaseController, UITableViewDelegat
|
||||
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
||||
let downloadTask = fetchedResultController.object(at: indexPath)
|
||||
guard let book = downloadTask.book else {return []}
|
||||
let cancel = UITableViewRowAction(style: .destructive, title: Localized.Common.cancel) { (action, indexPath) in
|
||||
var actions = [UITableViewRowAction(style: .destructive, title: Localized.Common.cancel) { (action, indexPath) in
|
||||
Network.shared.cancel(bookID: book.id)
|
||||
}]
|
||||
if downloadTask.state == .downloading {
|
||||
let pause = UITableViewRowAction(style: .normal, title: "Pause", handler: { _ in
|
||||
tableView.setEditing(false, animated: true)
|
||||
Network.shared.pause(bookID: book.id)
|
||||
})
|
||||
pause.backgroundColor = UIColor.orange
|
||||
actions.append(pause)
|
||||
} else if downloadTask.state == .paused {
|
||||
let resume = UITableViewRowAction(style: .normal, title: "Resume", handler: { (action, indexPath) in
|
||||
tableView.setEditing(false, animated: true)
|
||||
Network.shared.resume(bookID: book.id)
|
||||
})
|
||||
resume.backgroundColor = view.tintColor
|
||||
actions.append(resume)
|
||||
}
|
||||
return [cancel]
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
// MARK: - NSFetchedResultsController
|
||||
|
@ -10,7 +10,11 @@ import UIKit
|
||||
|
||||
class Network: NSObject, URLSessionDelegate, URLSessionTaskDelegate, URLSessionDownloadDelegate {
|
||||
static let shared = Network()
|
||||
private override init() {}
|
||||
private override init() {
|
||||
super.init()
|
||||
_ = wifiSession
|
||||
_ = cellularSession
|
||||
}
|
||||
var progresses = [String: Int64]()
|
||||
let managedObjectContext = AppDelegate.persistentContainer.viewContext
|
||||
var timer: Timer?
|
||||
@ -48,45 +52,38 @@ class Network: NSObject, URLSessionDelegate, URLSessionTaskDelegate, URLSessionD
|
||||
func pause(bookID: String) {
|
||||
cancelTask(in: wifiSession, taskDescription: bookID, producingResumingData: true)
|
||||
cancelTask(in: cellularSession, taskDescription: bookID, producingResumingData: true)
|
||||
|
||||
self.managedObjectContext.perform({
|
||||
guard let book = Book.fetch(bookID, context: self.managedObjectContext) else {return}
|
||||
if book.state != .downloading {book.state = .downloading}
|
||||
book.downloadTask?.state = .paused
|
||||
if self.managedObjectContext.hasChanges { try? self.managedObjectContext.save() }
|
||||
})
|
||||
}
|
||||
|
||||
func cancel(bookID: String) {
|
||||
cancelTask(in: wifiSession, taskDescription: bookID, producingResumingData: false)
|
||||
cancelTask(in: cellularSession, taskDescription: bookID, producingResumingData: false)
|
||||
|
||||
self.managedObjectContext.perform({
|
||||
guard let book = Book.fetch(bookID, context: self.managedObjectContext) else {return}
|
||||
book.meta4URL != nil ? book.state = .cloud : self.managedObjectContext.delete(book)
|
||||
if let downloadTask = book.downloadTask {self.managedObjectContext.delete(downloadTask)}
|
||||
if self.managedObjectContext.hasChanges { try? self.managedObjectContext.save() }
|
||||
})
|
||||
}
|
||||
|
||||
func resume(bookID: String) {
|
||||
|
||||
}
|
||||
|
||||
private func cancelTask(in session: URLSession, taskDescription: String, producingResumingData: Bool) {
|
||||
session.getTasksWithCompletionHandler { (_, _, downloadTasks) in
|
||||
func updateCoreData(bookID: String) {
|
||||
self.managedObjectContext.perform({
|
||||
guard let book = Book.fetch(taskDescription, context: self.managedObjectContext) else {return}
|
||||
if let _ = book.url {
|
||||
book.state = .cloud
|
||||
} else {
|
||||
self.managedObjectContext.delete(book)
|
||||
}
|
||||
|
||||
guard let downloadTask = book.downloadTask else {return}
|
||||
if producingResumingData {
|
||||
downloadTask.state = .paused
|
||||
} else {
|
||||
self.managedObjectContext.delete(downloadTask)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if let task = downloadTasks.filter({$0.taskDescription == taskDescription}).first {
|
||||
if producingResumingData {
|
||||
task.cancel(byProducingResumeData: { (data) in
|
||||
// save data
|
||||
updateCoreData(bookID: taskDescription)
|
||||
})
|
||||
} else {
|
||||
task.cancel()
|
||||
updateCoreData(bookID: taskDescription)
|
||||
}
|
||||
guard let task = downloadTasks.filter({$0.taskDescription == taskDescription}).first else {return}
|
||||
if producingResumingData {
|
||||
task.cancel(byProducingResumeData: {data in Preference.resumeData[taskDescription] = data })
|
||||
} else {
|
||||
updateCoreData(bookID: taskDescription)
|
||||
task.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,11 +103,19 @@ class Network: NSObject, URLSessionDelegate, URLSessionTaskDelegate, URLSessionD
|
||||
|
||||
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
||||
guard let bookID = task.taskDescription else {return}
|
||||
if let data = (error as NSError?)?.userInfo[NSURLSessionDownloadTaskResumeData] as? Data {
|
||||
Preference.resumeData[bookID] = data
|
||||
progresses[bookID] = nil
|
||||
if progresses.count == 0 { timer?.invalidate() }
|
||||
|
||||
if let error = error as NSError?, error.code == URLError.cancelled.rawValue {
|
||||
self.managedObjectContext.perform({
|
||||
guard let book = Book.fetch(bookID, context: self.managedObjectContext) else {return}
|
||||
guard book.downloadTask?.state != .paused else {return}
|
||||
if let data = error.userInfo[NSURLSessionDownloadTaskResumeData] as? Data {
|
||||
Preference.resumeData[bookID] = data
|
||||
}
|
||||
if book.state != .downloading {book.state = .downloading}
|
||||
book.downloadTask?.state = .paused
|
||||
if self.managedObjectContext.hasChanges { try? self.managedObjectContext.save() }
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -122,6 +127,7 @@ class Network: NSObject, URLSessionDelegate, URLSessionTaskDelegate, URLSessionD
|
||||
guard let bookID = downloadTask.taskDescription,
|
||||
let book = Book.fetch(bookID, context: self.managedObjectContext) else {return}
|
||||
if book.state != .downloading {book.state = .downloading}
|
||||
if book.downloadTask?.state != .downloading {book.downloadTask?.state = .downloading}
|
||||
self.progresses[bookID] = totalBytesWritten
|
||||
}
|
||||
}
|
||||
@ -129,9 +135,6 @@ class Network: NSObject, URLSessionDelegate, URLSessionTaskDelegate, URLSessionD
|
||||
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
||||
guard let bookID = downloadTask.taskDescription else {return}
|
||||
|
||||
progresses[bookID] = nil
|
||||
if progresses.count == 0 { timer?.invalidate() }
|
||||
|
||||
if let docDirURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
|
||||
let fileName = {
|
||||
return downloadTask.response?.suggestedFilename
|
||||
|
Loading…
x
Reference in New Issue
Block a user