diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2021-09-15 11:37:06 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2021-09-15 11:37:06 +0200 |
| commit | e5b9e8ddea9ce8f70f412d5a7b1f70c675161f30 (patch) | |
| tree | 7b203f7231bca703faa53b3223ff854c48e9b5a2 | |
| parent | 9375bbe666b7e02491b39f31291b45a38a335af3 (diff) | |
| parent | 7fee1788e6a736e57dbe843d0c73533ddad804ba (diff) | |
| download | mullvadvpn-e5b9e8ddea9ce8f70f412d5a7b1f70c675161f30.tar.xz mullvadvpn-e5b9e8ddea9ce8f70f412d5a7b1f70c675161f30.zip | |
Merge branch 'refactor-alert-presenter'
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 4 | ||||
| -rw-r--r-- | ios/MullvadVPN/AlertPresenter.swift | 55 | ||||
| -rw-r--r-- | ios/MullvadVPN/Operations/PresentAlertOperation.swift | 77 |
3 files changed, 95 insertions, 41 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 12f9d22b1e..b478a6570d 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 581FC4FA2695ACE100AA97BA /* Account.strings in Resources */ = {isa = PBXBuildFile; fileRef = 581FC4F82695ACE100AA97BA /* Account.strings */; }; 5820674926E63EC900655B05 /* Promise+BackgroundTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820674826E63EC800655B05 /* Promise+BackgroundTask.swift */; }; 5823FA5026CA690600283BF8 /* OSLogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5823FA4F26CA690600283BF8 /* OSLogHandler.swift */; }; + 5820675E26E6839900655B05 /* PresentAlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820675D26E6839900655B05 /* PresentAlertOperation.swift */; }; 58293FAE2510CA58005D0BB5 /* ProblemReportViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58293FAC2510CA58005D0BB5 /* ProblemReportViewController.swift */; }; 58293FB125124117005D0BB5 /* CustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58293FB025124117005D0BB5 /* CustomTextField.swift */; }; 58293FB3251241B4005D0BB5 /* CustomTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58293FB2251241B3005D0BB5 /* CustomTextView.swift */; }; @@ -319,6 +320,7 @@ 581CBCED229826FD00727D7F /* StaticTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticTableViewDataSource.swift; sourceTree = "<group>"; }; 581FC4F92695ACE100AA97BA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Account.strings; sourceTree = "<group>"; }; 5820674826E63EC800655B05 /* Promise+BackgroundTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Promise+BackgroundTask.swift"; sourceTree = "<group>"; }; + 5820675D26E6839900655B05 /* PresentAlertOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresentAlertOperation.swift; sourceTree = "<group>"; }; 5823FA4F26CA690600283BF8 /* OSLogHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSLogHandler.swift; sourceTree = "<group>"; }; 58293FAC2510CA58005D0BB5 /* ProblemReportViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProblemReportViewController.swift; sourceTree = "<group>"; }; 58293FB025124117005D0BB5 /* CustomTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextField.swift; sourceTree = "<group>"; }; @@ -533,6 +535,7 @@ 58E973DD24850EB600096F90 /* AsyncOperation.swift */, 580EE20524B3222200F9D8A1 /* ExclusivityController.swift */, 5846226926E0E6FA0035F7C2 /* ReceiptRefreshOperation.swift */, + 5820675D26E6839900655B05 /* PresentAlertOperation.swift */, ); path = Operations; sourceTree = "<group>"; @@ -1193,6 +1196,7 @@ 5835B7CC233B76CB0096D79F /* TunnelManager.swift in Sources */, 58FEEB46260A028D00A621A8 /* GeoJSON.swift in Sources */, 5815039724D6ECAE00C9C50E /* CustomFormatLogHandler.swift in Sources */, + 5820675E26E6839900655B05 /* PresentAlertOperation.swift in Sources */, 5815039D24D6ECE600C9C50E /* TextFileOutputStream.swift in Sources */, 581CBCEE229826FD00727D7F /* StaticTableViewDataSource.swift in Sources */, 58CE5E64224146200008646E /* AppDelegate.swift in Sources */, diff --git a/ios/MullvadVPN/AlertPresenter.swift b/ios/MullvadVPN/AlertPresenter.swift index 8594c8211e..954a641e28 100644 --- a/ios/MullvadVPN/AlertPresenter.swift +++ b/ios/MullvadVPN/AlertPresenter.swift @@ -9,20 +9,20 @@ import Foundation import UIKit -private let kUIAlertControllerDidDissmissNotification = Notification.Name("UIAlertControllerDidDismiss") - class AlertPresenter { - private enum ExclusivityCategory { - case exclusive - } + static let alertControllerDidDismissNotification = Notification.Name("UIAlertControllerDidDismiss") - private let operationQueue = OperationQueue() - private lazy var exclusivityController = ExclusivityController<ExclusivityCategory>(operationQueue: operationQueue) + private let operationQueue: OperationQueue = { + let operationQueue = OperationQueue() + operationQueue.name = "AlertPresenterQueue" + operationQueue.maxConcurrentOperationCount = 1 + return operationQueue + }() private static let initClass: Void = { /// Swizzle `viewDidDisappear` on `UIAlertController` in order to be able to /// detect when the controller disappears. - /// The event is broadcasted via `kUIAlertControllerDidDissmissNotification` notification. + /// The event is broadcasted via `AlertPresenter.alertControllerDidDismissNotification` notification. swizzleMethod(aClass: UIAlertController.self, originalSelector: #selector(UIAlertController.viewDidDisappear(_:)), newSelector: #selector(UIAlertController.alertPresenter_viewDidDisappear(_:))) }() @@ -37,11 +37,14 @@ class AlertPresenter { presentCompletion: presentCompletion ) - exclusivityController.addOperation(operation, categories: [.exclusive]) + operationQueue.addOperation(operation) } -} + func cancelAll() { + operationQueue.cancelAllOperations() + } +} fileprivate extension UIAlertController { @objc dynamic func alertPresenter_viewDidDisappear(_ animated: Bool) { @@ -49,37 +52,7 @@ fileprivate extension UIAlertController { alertPresenter_viewDidDisappear(animated) if presentingViewController == nil { - NotificationCenter.default.post(name: kUIAlertControllerDidDissmissNotification, object: self) - } - } -} - - -private class PresentAlertOperation: AsyncOperation { - private let alertController: UIAlertController - private let presentingController: UIViewController - private var dismissalObserver: NSObjectProtocol? - private let presentCompletion: (() -> Void)? - - init(alertController: UIAlertController, presentingController: UIViewController, presentCompletion: (() -> Void)? = nil) { - self.alertController = alertController - self.presentingController = presentingController - self.presentCompletion = presentCompletion - - super.init() - } - - override func main() { - DispatchQueue.main.async { - self.dismissalObserver = NotificationCenter.default.addObserver( - forName: kUIAlertControllerDidDissmissNotification, - object: self.alertController, - queue: nil, - using: { [weak self] (note) in - self?.finish() - }) - - self.presentingController.present(self.alertController, animated: true, completion: self.presentCompletion) + NotificationCenter.default.post(name: AlertPresenter.alertControllerDidDismissNotification, object: self) } } } diff --git a/ios/MullvadVPN/Operations/PresentAlertOperation.swift b/ios/MullvadVPN/Operations/PresentAlertOperation.swift new file mode 100644 index 0000000000..0bc420f770 --- /dev/null +++ b/ios/MullvadVPN/Operations/PresentAlertOperation.swift @@ -0,0 +1,77 @@ +// +// PresentAlertOperation.swift +// PresentAlertOperation +// +// Created by pronebird on 06/09/2021. +// Copyright © 2021 Mullvad VPN AB. All rights reserved. +// + +import UIKit + +class PresentAlertOperation: AsyncOperation { + private let alertController: UIAlertController + private let presentingController: UIViewController + private let presentCompletion: (() -> Void)? + + init(alertController: UIAlertController, presentingController: UIViewController, presentCompletion: (() -> Void)? = nil) { + self.alertController = alertController + self.presentingController = presentingController + self.presentCompletion = presentCompletion + + super.init() + } + + override func cancel() { + DispatchQueue.main.async { + // Guard against executing cancellation more than once. + guard !self.isCancelled else { return } + + // Guard against trying to dismiss the alert when operation hasn't started yet. + guard self.isExecuting else { return } + + // Guard against dismissing controller during transition. + if !self.alertController.isBeingPresented && !self.alertController.isBeingDismissed { + self.dismissAndFinish() + } + + // Call super implementation to toggle isCancelled flag + super.cancel() + } + } + + override func main() { + DispatchQueue.main.async { + NotificationCenter.default.addObserver( + self, + selector: #selector(self.alertControllerDidDismiss(_:)), + name: AlertPresenter.alertControllerDidDismissNotification, + object: self.alertController + ) + + self.presentingController.present(self.alertController, animated: true) { + self.presentCompletion?() + + // Alert operation was cancelled during transition? + if self.isCancelled { + self.dismissAndFinish() + } + } + } + } + + private func dismissAndFinish() { + NotificationCenter.default.removeObserver( + self, + name: AlertPresenter.alertControllerDidDismissNotification, + object: self.alertController + ) + + alertController.dismiss(animated: false) { + self.finish() + } + } + + @objc private func alertControllerDidDismiss(_ note: Notification) { + finish() + } +} |
