ParallelWorker.swift 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //
  2. // ParallelWorker.swift
  3. // Nextcloud
  4. //
  5. // Created by Henrik Storch on 18.02.22.
  6. // Copyright © 2022 Henrik Storch. All rights reserved.
  7. //
  8. // Author Henrik Storch <henrik.storch@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import UIKit
  24. import JGProgressHUD
  25. /// Object to execute multiple tasks in parallel like uploading or downloading.
  26. /// - Can display a progress indicator with status message
  27. /// - Can be canceled by user
  28. class ParallelWorker {
  29. let completionGroup = DispatchGroup()
  30. let queue = DispatchQueue(label: "ParallelWorker")
  31. let semaphore: DispatchSemaphore
  32. let titleKey: String
  33. var hud: JGProgressHUD?
  34. var totalTasks: Int?
  35. var completedTasks = 0
  36. var isCancelled = false
  37. /// Creates a ParallelWorker
  38. /// - Parameters:
  39. /// - n: Amount of tasks to be executed in parallel
  40. /// - titleKey: Localized String key, used for the status. Default: *Please Wait...*
  41. /// - totalTasks: Number of total tasks, if known
  42. /// - hudView: The parent view or current view which should present the progress indicator. If `nil`, no progress indicator will be shown.
  43. init(n: Int, titleKey: String?, totalTasks: Int?, hudView: UIView?) {
  44. semaphore = DispatchSemaphore(value: n)
  45. self.totalTasks = totalTasks
  46. self.titleKey = titleKey ?? "_wait_"
  47. guard let hudView = hudView else { return }
  48. DispatchQueue.main.async {
  49. let hud = JGProgressHUD()
  50. hud.show(in: hudView)
  51. hud.textLabel.text = NSLocalizedString(self.titleKey, comment: "")
  52. hud.detailTextLabel.text = NSLocalizedString("_tap_to_cancel_", comment: "")
  53. hud.tapOnHUDViewBlock = { hud in
  54. self.isCancelled = true
  55. // Cancel all download
  56. NCNetworking.shared.cancelAllDownloadTransfer()
  57. hud.dismiss()
  58. }
  59. self.hud = hud
  60. }
  61. }
  62. /// Execute
  63. /// - Parameter task: The task to execute. Needs to call `completion()` when done so the next task can be executed.
  64. func execute(task: @escaping (_ completion: @escaping () -> Void) -> Void) {
  65. completionGroup.enter()
  66. queue.async {
  67. self.semaphore.wait()
  68. guard !self.isCancelled else { return self.completionGroup.leave() }
  69. task {
  70. self.completedTasks += 1
  71. DispatchQueue.main.async {
  72. self.hud?.textLabel.text = "\(NSLocalizedString(self.titleKey, comment: "")) \(self.completedTasks) "
  73. if let totalTasks = self.totalTasks {
  74. self.hud?.textLabel.text?.append("\(NSLocalizedString("_of_", comment: "")) \(totalTasks)")
  75. } else {
  76. self.hud?.textLabel.text?.append(NSLocalizedString("_files_", comment: ""))
  77. }
  78. }
  79. self.semaphore.signal()
  80. self.completionGroup.leave()
  81. }
  82. }
  83. }
  84. /// Indicates that all tasks have been scheduled. Some tasks might still be in progress.
  85. /// - Parameter completion: Will be called after all tasks have finished
  86. func completeWork(completion: (() -> Void)? = nil) {
  87. completionGroup.notify(queue: .main) {
  88. guard !self.isCancelled else { return }
  89. self.hud?.indicatorView = JGProgressHUDSuccessIndicatorView()
  90. self.hud?.textLabel.text = NSLocalizedString("_done_", comment: "")
  91. self.hud?.detailTextLabel.text = ""
  92. self.hud?.dismiss(afterDelay: 1)
  93. completion?()
  94. }
  95. }
  96. }