summaryrefslogtreecommitdiffhomepage
path: root/ios/Operations/AlertPresenter.swift
blob: 1af6a9435dfb8dd7ca3110ec7c77bcb240ee2f0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//
//  AlertPresenter.swift
//  MullvadVPN
//
//  Created by pronebird on 04/06/2020.
//  Copyright © 2020 Mullvad VPN AB. All rights reserved.
//

#if canImport(UIKit)

import UIKit

public final class AlertPresenter {
    static let alertControllerDidDismissNotification = Notification
        .Name("UIAlertControllerDidDismiss")

    private let operationQueue: OperationQueue = {
        let operationQueue = AsyncOperationQueue()
        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
        /// `AlertPresenter.alertControllerDidDismissNotification` notification.
        swizzleMethod(
            aClass: UIAlertController.self,
            originalSelector: #selector(UIAlertController.viewDidDisappear(_:)),
            newSelector: #selector(UIAlertController.alertPresenter_viewDidDisappear(_:))
        )
    }()

    public init() {
        _ = Self.initClass
    }

    public func enqueue(
        _ alertController: UIAlertController,
        presentingController: UIViewController,
        presentCompletion: (() -> Void)? = nil
    ) {
        let operation = PresentAlertOperation(
            alertController: alertController,
            presentingController: presentingController,
            presentCompletion: presentCompletion
        )

        operationQueue.addOperation(operation)
    }

    public func cancelAll() {
        operationQueue.cancelAllOperations()
    }
}

private extension UIAlertController {
    @objc dynamic func alertPresenter_viewDidDisappear(_ animated: Bool) {
        // Call super implementation
        alertPresenter_viewDidDisappear(animated)

        if presentingViewController == nil {
            NotificationCenter.default.post(
                name: AlertPresenter.alertControllerDidDismissNotification,
                object: self
            )
        }
    }
}

#endif