diff --git a/iphone/Maps/Classes/MapsAppDelegate.mm b/iphone/Maps/Classes/MapsAppDelegate.mm index f38156d0b5..f22a32cfad 100644 --- a/iphone/Maps/Classes/MapsAppDelegate.mm +++ b/iphone/Maps/Classes/MapsAppDelegate.mm @@ -381,9 +381,7 @@ using namespace osm_auth_ios; - (void)runBackgroundTasks:(NSArray * _Nonnull)tasks completionHandler:(void (^_Nullable)(UIBackgroundFetchResult))completionHandler { - __weak auto wSelf = self; auto completion = ^(UIBackgroundFetchResult result) { - wSelf.backgroundFetchScheduler = nil; if (completionHandler) completionHandler(result); }; diff --git a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchScheduler.swift b/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchScheduler.swift index 2879547094..f3fc5d193b 100644 --- a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchScheduler.swift +++ b/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchScheduler.swift @@ -2,27 +2,26 @@ final class BackgroundFetchScheduler: NSObject { typealias FetchResultHandler = (UIBackgroundFetchResult) -> Void - enum Const { - static let timeoutSafetyIndent: TimeInterval = 1 - } - private let completionHandler: FetchResultHandler private let tasks: [BackgroundFetchTask] - private let tasksGroup = DispatchGroup() - private var fetchResult = UIBackgroundFetchResult.noData + private var tasksLeft: Int + private var bestResultSoFar = UIBackgroundFetchResult.noData @objc init(tasks: [BackgroundFetchTask], completionHandler: @escaping FetchResultHandler) { self.tasks = tasks self.completionHandler = completionHandler + tasksLeft = tasks.count super.init() } @objc func run() { - DispatchQueue.main.async { - self.fullfillFrameworkRequirements() - let timeout = DispatchTime.now() + UIApplication.shared.backgroundTimeRemaining - Const.timeoutSafetyIndent - self.performTasks(timeout: timeout) + fullfillFrameworkRequirements() + + let completionHandler: FetchResultHandler = { [weak self] result in + self?.finishTask(result: result) } + + tasks.forEach { $0.start(completion: completionHandler) } } private func fullfillFrameworkRequirements() { @@ -33,56 +32,25 @@ final class BackgroundFetchScheduler: NSObject { return tasks.reduce(.none) { max($0, $1.frameworkType) } } - private func performTasks(timeout: DispatchTime) { - DispatchQueue.global().async { - self.setCompletionHandlers() - self.startTasks() - self.waitTasks(timeout: timeout) - } - } - - private func setCompletionHandlers() { - let completionHandler: FetchResultHandler = { [weak self] result in - self?.finishTask(result: result) - } - tasks.forEach { $0.completionHandler = completionHandler } - } - - private func startTasks() { - tasks.forEach { - tasksGroup.enter() - $0.start() - } - } - private func finishTask(result: UIBackgroundFetchResult) { updateFetchResult(result) - tasksGroup.leave() - } - - private func waitTasks(timeout: DispatchTime) { - let groupCompletion = tasksGroup.wait(timeout: timeout) - DispatchQueue.main.async { - switch groupCompletion { - case .success: self.completionHandler(self.fetchResult) - case .timedOut: self.completionHandler(.failed) - } + tasksLeft -= 1 + if tasksLeft <= 0 { + completionHandler(bestResultSoFar) } } private func updateFetchResult(_ result: UIBackgroundFetchResult) { - DispatchQueue.main.async { - if self.resultPriority(self.fetchResult) < self.resultPriority(result) { - self.fetchResult = result - } + if resultPriority(bestResultSoFar) < resultPriority(result) { + bestResultSoFar = result } } private func resultPriority(_ result: UIBackgroundFetchResult) -> Int { switch result { - case .newData: return 2 - case .noData: return 1 - case .failed: return 3 + case .newData: return 3 + case .noData: return 1 + case .failed: return 2 } } } diff --git a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundDownloadMapNotification.swift b/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundDownloadMapNotification.swift deleted file mode 100644 index a1a20e21c4..0000000000 --- a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundDownloadMapNotification.swift +++ /dev/null @@ -1,9 +0,0 @@ -@objc(MWMBackgroundDownloadMapNotification) -final class BackgroundDownloadMapNotification: BackgroundFetchTask { - override var queue: DispatchQueue { return .main } - override var frameworkType: BackgroundFetchTaskFrameworkType { return .full } - - override lazy var block = { - LocalNotificationManager.shared().showDownloadMapNotificationIfNeeded(self.finish) - } -} diff --git a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundEditsUpload.swift b/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundEditsUpload.swift deleted file mode 100644 index 8ea48abbf2..0000000000 --- a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundEditsUpload.swift +++ /dev/null @@ -1,6 +0,0 @@ -@objc(MWMBackgroundEditsUpload) -final class BackgroundEditsUpload: BackgroundFetchTask { - override lazy var block = { - MWMEditorHelper.uploadEdits(self.finish) - } -} diff --git a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundFetchTask.swift b/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundFetchTask.swift index b316f3a9fe..6f1e0b80a3 100644 --- a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundFetchTask.swift +++ b/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundFetchTask.swift @@ -1,31 +1,76 @@ @objc class BackgroundFetchTask: NSObject { - var queue: DispatchQueue { return .global() } var frameworkType: BackgroundFetchTaskFrameworkType { return .none } private var backgroundTaskIdentifier = UIBackgroundTaskInvalid - lazy var block = { self.finish(.failed) } - var completionHandler: BackgroundFetchScheduler.FetchResultHandler! + private var completionHandler: BackgroundFetchScheduler.FetchResultHandler? - func start() { - DispatchQueue.main.async { - self.backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: { - self.finish(.failed) - }) - if self.backgroundTaskIdentifier != UIBackgroundTaskInvalid { - self.queue.async(execute: self.block) - } - } + func start(completion: @escaping BackgroundFetchScheduler.FetchResultHandler) { + completionHandler = completion + backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(withName:description, + expirationHandler: { + self.finish(.failed) + }) + if backgroundTaskIdentifier != UIBackgroundTaskInvalid { fire() } } - func finish(_ result: UIBackgroundFetchResult) { + fileprivate func fire() { + finish(.failed) + } + + fileprivate func finish(_ result: UIBackgroundFetchResult) { guard backgroundTaskIdentifier != UIBackgroundTaskInvalid else { return } - DispatchQueue.main.async { - UIApplication.shared.endBackgroundTask(self.backgroundTaskIdentifier) - self.backgroundTaskIdentifier = UIBackgroundTaskInvalid - self.queue.async { - self.completionHandler(result) - } - } + UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier) + backgroundTaskIdentifier = UIBackgroundTaskInvalid + completionHandler?(result) } } + +@objc(MWMBackgroundStatisticsUpload) +final class BackgroundStatisticsUpload: BackgroundFetchTask { + override fileprivate func fire() { + Alohalytics.forceUpload(self.finish) + } + + override var description: String { + return "Statistics upload" + } +} + +@objc(MWMBackgroundEditsUpload) +final class BackgroundEditsUpload: BackgroundFetchTask { + override fileprivate func fire() { + MWMEditorHelper.uploadEdits(self.finish) + } + + override var description: String { + return "Edits upload" + } +} + +@objc(MWMBackgroundUGCUpload) +final class BackgroundUGCUpload: BackgroundFetchTask { + override var frameworkType: BackgroundFetchTaskFrameworkType { return .full } + + override fileprivate func fire() { + MWMUGCHelper.uploadEdits(self.finish) + } + + override var description: String { + return "UGC upload" + } +} + +@objc(MWMBackgroundDownloadMapNotification) +final class BackgroundDownloadMapNotification: BackgroundFetchTask { + override var frameworkType: BackgroundFetchTaskFrameworkType { return .full } + + override fileprivate func fire() { + LocalNotificationManager.shared().showDownloadMapNotificationIfNeeded(self.finish) + } + + override var description: String { + return "Download map notification" + } +} + diff --git a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundStatisticsUpload.swift b/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundStatisticsUpload.swift deleted file mode 100644 index 42b42994fb..0000000000 --- a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundStatisticsUpload.swift +++ /dev/null @@ -1,6 +0,0 @@ -@objc(MWMBackgroundStatisticsUpload) -final class BackgroundStatisticsUpload: BackgroundFetchTask { - override lazy var block = { - Alohalytics.forceUpload(self.finish) - } -} diff --git a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundUGCUpload.swift b/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundUGCUpload.swift deleted file mode 100644 index c1204c1f6f..0000000000 --- a/iphone/Maps/Core/BackgroundFetchScheduler/BackgroundFetchTask/BackgroundUGCUpload.swift +++ /dev/null @@ -1,9 +0,0 @@ -@objc(MWMBackgroundUGCUpload) -final class BackgroundUGCUpload: BackgroundFetchTask { - override var queue: DispatchQueue { return .main } - override var frameworkType: BackgroundFetchTaskFrameworkType { return .full } - - override lazy var block = { - MWMUGCHelper.uploadEdits(self.finish) - } -} diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index af8d110c25..4938a4285f 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -143,12 +143,8 @@ 3472B5CB200F43EF00DC6CD5 /* BackgroundFetchScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3472B5C9200F43EF00DC6CD5 /* BackgroundFetchScheduler.swift */; }; 3472B5CF200F4A2B00DC6CD5 /* BackgroundFetchTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3472B5CD200F4A2B00DC6CD5 /* BackgroundFetchTask.swift */; }; 3472B5D3200F501500DC6CD5 /* BackgroundFetchTaskFrameworkType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3472B5D1200F501500DC6CD5 /* BackgroundFetchTaskFrameworkType.swift */; }; - 3472B5D7200F61E900DC6CD5 /* BackgroundStatisticsUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3472B5D5200F61E900DC6CD5 /* BackgroundStatisticsUpload.swift */; }; - 3472B5DB200F7C1000DC6CD5 /* BackgroundEditsUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3472B5D9200F7C1000DC6CD5 /* BackgroundEditsUpload.swift */; }; 3472B5E1200F86C800DC6CD5 /* MWMEditorHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3472B5DF200F86C800DC6CD5 /* MWMEditorHelper.mm */; }; 3472B5EB200F8CFF00DC6CD5 /* MWMUGCHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3472B5E9200F8CFF00DC6CD5 /* MWMUGCHelper.mm */; }; - 3472B5EF200F8F7600DC6CD5 /* BackgroundUGCUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3472B5ED200F8F7600DC6CD5 /* BackgroundUGCUpload.swift */; }; - 3472B5F3200F906800DC6CD5 /* BackgroundDownloadMapNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3472B5F1200F906800DC6CD5 /* BackgroundDownloadMapNotification.swift */; }; 34763EE71F2F392300F4D2D3 /* MWMTextToSpeech.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34763EE51F2F392300F4D2D3 /* MWMTextToSpeech.mm */; }; 34763F071F3092E700F4D2D3 /* String+Format.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34763F051F3092E700F4D2D3 /* String+Format.swift */; }; 3476B8DD1BFDD30B00874594 /* tts-how-to-set-up-voice.html in Resources */ = {isa = PBXBuildFile; fileRef = 3476B8D51BFDD30B00874594 /* tts-how-to-set-up-voice.html */; }; @@ -913,14 +909,10 @@ 3472B5C9200F43EF00DC6CD5 /* BackgroundFetchScheduler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundFetchScheduler.swift; sourceTree = ""; }; 3472B5CD200F4A2B00DC6CD5 /* BackgroundFetchTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundFetchTask.swift; sourceTree = ""; }; 3472B5D1200F501500DC6CD5 /* BackgroundFetchTaskFrameworkType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundFetchTaskFrameworkType.swift; sourceTree = ""; }; - 3472B5D5200F61E900DC6CD5 /* BackgroundStatisticsUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundStatisticsUpload.swift; sourceTree = ""; }; - 3472B5D9200F7C1000DC6CD5 /* BackgroundEditsUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundEditsUpload.swift; sourceTree = ""; }; 3472B5DE200F86C800DC6CD5 /* MWMEditorHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMEditorHelper.h; sourceTree = ""; }; 3472B5DF200F86C800DC6CD5 /* MWMEditorHelper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMEditorHelper.mm; sourceTree = ""; }; 3472B5E8200F8CFF00DC6CD5 /* MWMUGCHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMUGCHelper.h; sourceTree = ""; }; 3472B5E9200F8CFF00DC6CD5 /* MWMUGCHelper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMUGCHelper.mm; sourceTree = ""; }; - 3472B5ED200F8F7600DC6CD5 /* BackgroundUGCUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundUGCUpload.swift; sourceTree = ""; }; - 3472B5F1200F906800DC6CD5 /* BackgroundDownloadMapNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundDownloadMapNotification.swift; sourceTree = ""; }; 347526FA1DC0B00F00918CF5 /* common-debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "common-debug.xcconfig"; path = "../../xcode/common-debug.xcconfig"; sourceTree = ""; }; 347526FB1DC0B00F00918CF5 /* common-release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "common-release.xcconfig"; path = "../../xcode/common-release.xcconfig"; sourceTree = ""; }; 34763EE41F2F392300F4D2D3 /* MWMTextToSpeech.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMTextToSpeech.h; sourceTree = ""; }; @@ -2550,10 +2542,6 @@ isa = PBXGroup; children = ( 3472B5CD200F4A2B00DC6CD5 /* BackgroundFetchTask.swift */, - 3472B5D5200F61E900DC6CD5 /* BackgroundStatisticsUpload.swift */, - 3472B5D9200F7C1000DC6CD5 /* BackgroundEditsUpload.swift */, - 3472B5ED200F8F7600DC6CD5 /* BackgroundUGCUpload.swift */, - 3472B5F1200F906800DC6CD5 /* BackgroundDownloadMapNotification.swift */, ); path = BackgroundFetchTask; sourceTree = ""; @@ -4311,14 +4299,12 @@ 3408963F1F83CEDE00BC7117 /* MWMAuthorizationViewModel.mm in Sources */, F6E2FE1F1E097BA00083EBEC /* MWMOpeningHoursCommon.mm in Sources */, 3454D7B91E07F045004AF2AD /* CALayer+RuntimeAttributes.mm in Sources */, - 3472B5DB200F7C1000DC6CD5 /* BackgroundEditsUpload.swift in Sources */, F6E2FF5D1E097BA00083EBEC /* MWMRecentTrackSettingsController.mm in Sources */, 34AB66651FC5AA330078E451 /* TransportTransitTrain.swift in Sources */, 343064411E9FDC7300DC7665 /* SearchIndex.swift in Sources */, F6664BFA1E6459CB00E703C2 /* PPFacilityCell.swift in Sources */, 348B926D1FF3B5E100379009 /* UIView+Animation.swift in Sources */, F6E2FDE91E097BA00083EBEC /* MWMObjectsCategorySelectorController.mm in Sources */, - 3472B5EF200F8F7600DC6CD5 /* BackgroundUGCUpload.swift in Sources */, 6741A9A81BF340DE002C974C /* MWMFacebookAlert.mm in Sources */, 34AB665F1FC5AA330078E451 /* TransportTransitIntermediatePoint.swift in Sources */, 34B846A82029E8110081ECCD /* BMCDefaultViewModel.swift in Sources */, @@ -4437,7 +4423,6 @@ 349D1ACF1E2E325B004A2006 /* MWMBottomMenuCollectionViewCell.mm in Sources */, F6E2FF451E097BA00083EBEC /* SettingsTableViewLinkCell.swift in Sources */, 34C9BD0A1C6DBCDA000DC38D /* MWMNavigationController.mm in Sources */, - 3472B5F3200F906800DC6CD5 /* BackgroundDownloadMapNotification.swift in Sources */, F6550C1F1FD81B3800352D88 /* RatingSummaryView+DefaultConfig.swift in Sources */, F6E2FE311E097BA00083EBEC /* MWMStreetEditorViewController.mm in Sources */, F6E2FE281E097BA00083EBEC /* MWMOpeningHoursSection.mm in Sources */, @@ -4547,7 +4532,6 @@ F6E2FD6B1E097BA00083EBEC /* MWMMapDownloaderSubplaceTableViewCell.mm in Sources */, 3409D50B1FC6D8D2000F9B3E /* FilterCheckCell.swift in Sources */, 3472B5CB200F43EF00DC6CD5 /* BackgroundFetchScheduler.swift in Sources */, - 3472B5D7200F61E900DC6CD5 /* BackgroundStatisticsUpload.swift in Sources */, 34FE5A6F1F18F30F00BCA729 /* TrafficButtonArea.swift in Sources */, F6E2FF691E097BA00083EBEC /* MWMUnitsController.mm in Sources */, 6741AA031BF340DE002C974C /* MWMActivityViewController.mm in Sources */,