summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2021-09-15 11:37:06 +0200
committerAndrej Mihajlov <and@mullvad.net>2021-09-15 11:37:06 +0200
commite5b9e8ddea9ce8f70f412d5a7b1f70c675161f30 (patch)
tree7b203f7231bca703faa53b3223ff854c48e9b5a2
parent9375bbe666b7e02491b39f31291b45a38a335af3 (diff)
parent7fee1788e6a736e57dbe843d0c73533ddad804ba (diff)
downloadmullvadvpn-e5b9e8ddea9ce8f70f412d5a7b1f70c675161f30.tar.xz
mullvadvpn-e5b9e8ddea9ce8f70f412d5a7b1f70c675161f30.zip
Merge branch 'refactor-alert-presenter'
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj4
-rw-r--r--ios/MullvadVPN/AlertPresenter.swift55
-rw-r--r--ios/MullvadVPN/Operations/PresentAlertOperation.swift77
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()
+ }
+}