diff --git a/MVMCore/MVMCore.xcodeproj/project.pbxproj b/MVMCore/MVMCore.xcodeproj/project.pbxproj index bdd9165..d8718e9 100644 --- a/MVMCore/MVMCore.xcodeproj/project.pbxproj +++ b/MVMCore/MVMCore.xcodeproj/project.pbxproj @@ -107,6 +107,11 @@ AF7069A02880F0EB00077CF6 /* ActionOpenPageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF70699F2880F0EB00077CF6 /* ActionOpenPageHandler.swift */; }; AF787413286DEF8B00670588 /* ActionBackHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF787412286DEF8B00670588 /* ActionBackHandler.swift */; }; AF8D13392774EA1D008AF4A9 /* ActionOpenUrlHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF8D13382774EA1D008AF4A9 /* ActionOpenUrlHandler.swift */; }; + AF925DEE28BD35A2008E8677 /* MVMCoreNavigationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF925DED28BD35A2008E8677 /* MVMCoreNavigationHandler.swift */; }; + AF925DF028BE78E2008E8677 /* MVMCoreNavigationPresentOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF925DEF28BE78E2008E8677 /* MVMCoreNavigationPresentOperation.swift */; }; + AF925DF428C0FA38008E8677 /* MVMCoreNavigationPushOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF925DF328C0FA38008E8677 /* MVMCoreNavigationPushOperation.swift */; }; + AF925DF628C10732008E8677 /* MVMCoreNavigationSetOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF925DF528C10732008E8677 /* MVMCoreNavigationSetOperation.swift */; }; + AF925DF828C10B00008E8677 /* MVMCoreNavigationPopOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF925DF728C10B00008E8677 /* MVMCoreNavigationPopOperation.swift */; }; AFBB96341FBA34310008D868 /* MVMCoreErrorConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB96321FBA34310008D868 /* MVMCoreErrorConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; AFBB96351FBA34310008D868 /* MVMCoreErrorConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96331FBA34310008D868 /* MVMCoreErrorConstants.m */; }; AFBB96381FBA39E70008D868 /* MVMCoreLoadDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB96371FBA39E70008D868 /* MVMCoreLoadDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -269,6 +274,11 @@ AF70699F2880F0EB00077CF6 /* ActionOpenPageHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionOpenPageHandler.swift; sourceTree = ""; }; AF787412286DEF8B00670588 /* ActionBackHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionBackHandler.swift; sourceTree = ""; }; AF8D13382774EA1D008AF4A9 /* ActionOpenUrlHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionOpenUrlHandler.swift; sourceTree = ""; }; + AF925DED28BD35A2008E8677 /* MVMCoreNavigationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationHandler.swift; sourceTree = ""; }; + AF925DEF28BE78E2008E8677 /* MVMCoreNavigationPresentOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationPresentOperation.swift; sourceTree = ""; }; + AF925DF328C0FA38008E8677 /* MVMCoreNavigationPushOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationPushOperation.swift; sourceTree = ""; }; + AF925DF528C10732008E8677 /* MVMCoreNavigationSetOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationSetOperation.swift; sourceTree = ""; }; + AF925DF728C10B00008E8677 /* MVMCoreNavigationPopOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationPopOperation.swift; sourceTree = ""; }; AFBB96321FBA34310008D868 /* MVMCoreErrorConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreErrorConstants.h; sourceTree = ""; }; AFBB96331FBA34310008D868 /* MVMCoreErrorConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreErrorConstants.m; sourceTree = ""; }; AFBB96371FBA39E70008D868 /* MVMCoreLoadDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreLoadDelegateProtocol.h; sourceTree = ""; }; @@ -592,10 +602,15 @@ AFBB966E1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.m */, AFBB966F1FBA3A9A0008D868 /* MVMCoreNavigationHandler.h */, AFBB96701FBA3A9A0008D868 /* MVMCoreNavigationHandler.m */, + AF925DED28BD35A2008E8677 /* MVMCoreNavigationHandler.swift */, AFBB96711FBA3A9A0008D868 /* MVMCoreNavigationObject.h */, AFBB96721FBA3A9A0008D868 /* MVMCoreNavigationObject.m */, AFBB96731FBA3A9A0008D868 /* MVMCoreNavigationOperation.h */, AFBB96741FBA3A9A0008D868 /* MVMCoreNavigationOperation.m */, + AF925DF328C0FA38008E8677 /* MVMCoreNavigationPushOperation.swift */, + AF925DF528C10732008E8677 /* MVMCoreNavigationSetOperation.swift */, + AF925DF728C10B00008E8677 /* MVMCoreNavigationPopOperation.swift */, + AF925DEF28BE78E2008E8677 /* MVMCoreNavigationPresentOperation.swift */, AFBB96751FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.h */, AFBB96761FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.m */, AFBB96771FBA3A9A0008D868 /* MVMCorePresentationDelegateProtocol.h */, @@ -893,6 +908,7 @@ AFBB96641FBA3A570008D868 /* MVMCoreLoadHandler.m in Sources */, AFFCFA671FCCC0D700FD0730 /* MVMCoreLoadingOverlayHandler.m in Sources */, AF8D13392774EA1D008AF4A9 /* ActionOpenUrlHandler.swift in Sources */, + AF925DEE28BD35A2008E8677 /* MVMCoreNavigationHandler.swift in Sources */, AF130B8E2788DF6E00C6C03C /* OpenURLOptionsModel.swift in Sources */, AF69D4EB286E586200BC6862 /* ActionRestartHandler.swift in Sources */, AFBB968E1FBA3A9A0008D868 /* MVMCoreNavigationHandler.m in Sources */, @@ -906,6 +922,7 @@ 01F2A04C23A82B1B00D954D8 /* ActionCallModel.swift in Sources */, 8876D5ED1FB50AB000EB2E3D /* NSDictionary+MFConvenience.m in Sources */, AFBB968C1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.m in Sources */, + AF925DF628C10732008E8677 /* MVMCoreNavigationSetOperation.swift in Sources */, AFBB96ED1FBA4A260008D868 /* MFHardCodedServerResponse.m in Sources */, AF43A74D1FC6109F008E9347 /* MVMCoreSessionObject.m in Sources */, D282AAB62240085300C46919 /* MVMCoreGetterUtility+Extension.swift in Sources */, @@ -918,6 +935,7 @@ 0A42538F23F3414800554656 /* Codable+Helpers.swift in Sources */, 881D26931FCC9D180079C521 /* MVMCoreErrorObject.m in Sources */, 94C014D124211869005811A9 /* ActionRestartModel.swift in Sources */, + AF925DF828C10B00008E8677 /* MVMCoreNavigationPopOperation.swift in Sources */, D288D5F526C6EFE000A5C365 /* MVMCoreLoggingHandler+Extension.swift in Sources */, 946EE1B0237B5EF70036751F /* JSONHelper.swift in Sources */, 30349BF21FCCA78A00546A1E /* MVMCoreSessionTimeHandler.m in Sources */, @@ -969,7 +987,9 @@ AFBB96921FBA3A9A0008D868 /* MVMCoreNavigationOperation.m in Sources */, AFBB96611FBA3A570008D868 /* MVMCoreLoadObject.m in Sources */, AF787413286DEF8B00670588 /* ActionBackHandler.swift in Sources */, + AF925DF428C0FA38008E8677 /* MVMCoreNavigationPushOperation.swift in Sources */, 946EE1B4237B619D0036751F /* Encoder.swift in Sources */, + AF925DF028BE78E2008E8677 /* MVMCoreNavigationPresentOperation.swift in Sources */, AF60A7F4289212EB00919EEB /* MVMCoreError.swift in Sources */, AFBB96941FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.m in Sources */, 94C014D524211AF0005811A9 /* ActionCancelModel.swift in Sources */, diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.swift b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.swift new file mode 100644 index 0000000..c5f1b19 --- /dev/null +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.swift @@ -0,0 +1,92 @@ +// +// MVMCoreNavigationHandler.swift +// MVMCore +// +// Created by Scott Pfeil on 8/29/22. +// Copyright © 2022 myverizon. All rights reserved. +// + +import Foundation + +@objc open class MVMCoreNavigationHandler2: NSObject, UINavigationControllerDelegate { + public enum NavigationType { + case push(viewController: UIViewController, navigationController: UINavigationController, animated: Bool = true) + case set(viewControllers: [UIViewController], navigationController: UINavigationController, animated: Bool = true) + case pop(navigationController: UINavigationController, animated: Bool = true) + case popTo(viewController: UIViewController, navigationController: UINavigationController, animated: Bool = true) + case present(viewController: UIViewController, onController: UIViewController, animated: Bool = true) + case dismiss(onController: UIViewController, animated: Bool = true) + } + + private static let handler = MVMCoreNavigationHandler2() + + @objc(sharedNavigationHandler) + public static func shared() -> MVMCoreNavigationHandler2 { + return handler + } + + let navigationQueue: OperationQueue = { + var queue = OperationQueue() + queue.maxConcurrentOperationCount = 1 + return queue + }() + + let delegates: NSHashTable = NSHashTable.weakObjects() + + // MARK: - Delegate Handling + + open func add(delegate: MVMCorePresentationDelegateProtocol) { + delegates.add(delegate) + } + + open func remove(delegate: MVMCorePresentationDelegateProtocol) { + delegates.remove(delegate) + } + + public func navigate(with type: NavigationType) async { + switch type { + case NavigationType.push(let viewController, let navigationController, let animated): + return + case NavigationType.present(let viewController, let onController, let animated): + await present(viewController: viewController, onViewController: onController, animated: animated) + default: + return + } + } + + open func present(viewController: UIViewController, onViewController: UIViewController, animated: Bool = true) async { + await withCheckedContinuation { continuation in + let operation = MVMCoreNavigationPresentOperation(with: viewController, presentingViewController: onViewController, animated: animated) + + // Gets the top most presented to use. + navigationQueue.addOperation { + MVMCoreDispatchUtility.performSyncBlock(onMainThread: { + var controllerToPresentOn = onViewController + while (controllerToPresentOn.presentedViewController != nil) { + controllerToPresentOn = controllerToPresentOn.presentedViewController! + } + operation.presentingViewController = controllerToPresentOn + }) + } + + // Notifies delegates we will present. + let token = operation.observe(\.isExecuting, options: .new) { (operation, change) in + guard change.newValue == true else { return } + self.delegates.allObjects.forEach { $0.viewController?(operation.presentingViewController, willPresent: operation.presentedViewController) + } + } + + operation.completionBlock = { + operation.completionBlock = nil + token.invalidate() + // Notifies delegates we presented. + if operation.isFinished { + self.delegates.allObjects.forEach { $0.viewController?(operation.presentingViewController, didPresent: operation.presentedViewController) + } + } + continuation.resume() + } + navigationQueue.addOperation(operation) + } as Void + } +} diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationPopOperation.swift b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationPopOperation.swift new file mode 100644 index 0000000..e69897e --- /dev/null +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationPopOperation.swift @@ -0,0 +1,43 @@ +// +// MVMCoreNavigationPopOperation.swift +// MVMCore +// +// Created by Scott Pfeil on 9/1/22. +// Copyright © 2022 myverizon. All rights reserved. +// + +import Foundation +import UIKit + +open class MVMCoreNavigationPopOperation: MVMCoreOperation, MVMCorePresentationDelegateProtocol { + open var navigationController: UINavigationController + open var animated: Bool + + private var previousViewController: UIViewController? + + public init(with navigationController: UINavigationController, animated: Bool = true) { + self.navigationController = navigationController + self.animated = animated + } + + open override func main() { + checkAndHandleForCancellation() + Task { @MainActor in + try Task.checkCancellation() + guard navigationController.viewControllers.count > 1 else { + markAsFinished() + return + } + previousViewController = navigationController.viewControllers[navigationController.viewControllers.count - 2] + MVMCoreNavigationHandler2.shared().add(delegate: self) + navigationController.popViewController(animated: animated) + } + } + + public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) { + guard self.navigationController == navigationController, + previousViewController == viewController else { return } + MVMCoreNavigationHandler2.shared().remove(delegate: self) + markAsFinished() + } +} diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationPresentOperation.swift b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationPresentOperation.swift new file mode 100644 index 0000000..0c73ddf --- /dev/null +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationPresentOperation.swift @@ -0,0 +1,32 @@ +// +// MVMCorePresentViewControllerOperation.swift +// MVMCore +// +// Created by Scott Pfeil on 8/30/22. +// Copyright © 2022 myverizon. All rights reserved. +// + +import Foundation +import UIKit + +open class MVMCoreNavigationPresentOperation: MVMCoreOperation { + open var presentedViewController: UIViewController + open var presentingViewController: UIViewController + open var animated: Bool + + public init(with presentedViewController: UIViewController, presentingViewController: UIViewController, animated: Bool = true) { + self.presentedViewController = presentedViewController + self.presentingViewController = presentingViewController + self.animated = animated + } + + open override func main() { + checkAndHandleForCancellation() + Task { @MainActor in + try Task.checkCancellation() + presentingViewController.present(presentedViewController, animated: animated) { + self.markAsFinished() + } + } + } +} diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationPushOperation.swift b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationPushOperation.swift new file mode 100644 index 0000000..4f9159b --- /dev/null +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationPushOperation.swift @@ -0,0 +1,38 @@ +// +// MVMCoreNavigationPushOperation.swift +// MVMCore +// +// Created by Scott Pfeil on 9/1/22. +// Copyright © 2022 myverizon. All rights reserved. +// + +import Foundation +import UIKit + +open class MVMCoreNavigationPushOperation: MVMCoreOperation, MVMCorePresentationDelegateProtocol { + open var viewController: UIViewController + open var navigationController: UINavigationController + open var animated: Bool + + public init(with viewController: UIViewController, navigationController: UINavigationController, animated: Bool = true) { + self.viewController = viewController + self.navigationController = navigationController + self.animated = animated + } + + open override func main() { + checkAndHandleForCancellation() + MVMCoreNavigationHandler2.shared().add(delegate: self) + Task { @MainActor in + try Task.checkCancellation() + navigationController.pushViewController(viewController, animated: animated) + } + } + + public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) { + guard self.navigationController == navigationController, + self.viewController == viewController else { return } + MVMCoreNavigationHandler2.shared().remove(delegate: self) + markAsFinished() + } +} diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationSetOperation.swift b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationSetOperation.swift new file mode 100644 index 0000000..4a28a74 --- /dev/null +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationSetOperation.swift @@ -0,0 +1,38 @@ +// +// MVMCoreNavigationSetOperation.swift +// MVMCore +// +// Created by Scott Pfeil on 9/1/22. +// Copyright © 2022 myverizon. All rights reserved. +// + +import Foundation +import UIKit + +open class MVMCoreNavigationSetOperation: MVMCoreOperation, MVMCorePresentationDelegateProtocol { + open var viewControllers: [UIViewController] + open var navigationController: UINavigationController + open var animated: Bool + + public init(with viewControllers: [UIViewController], navigationController: UINavigationController, animated: Bool = true) { + self.viewControllers = viewControllers + self.navigationController = navigationController + self.animated = animated + } + + open override func main() { + checkAndHandleForCancellation() + MVMCoreNavigationHandler2.shared().add(delegate: self) + Task { @MainActor in + try Task.checkCancellation() + navigationController.setViewControllers(viewControllers, animated: animated) + } + } + + public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) { + guard self.navigationController == navigationController, + viewControllers.last == viewController else { return } + MVMCoreNavigationHandler2.shared().remove(delegate: self) + markAsFinished() + } +} diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCorePresentViewControllerOperation.h b/MVMCore/MVMCore/PresentationHandling/MVMCorePresentViewControllerOperation.h index 1556a1c..07a7e6b 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCorePresentViewControllerOperation.h +++ b/MVMCore/MVMCore/PresentationHandling/MVMCorePresentViewControllerOperation.h @@ -6,15 +6,15 @@ // Copyright © 2015 Verizon Wireless. All rights reserved. // // An operation for presenting a view controller. Depends on alert as well. Should NOT go onto the main queue. - -#import -#import -#import - -@interface MVMCorePresentViewControllerOperation : MVMCoreOperation - -@property (nullable, weak, nonatomic) NSObject *delegate; - -- (nullable instancetype)initWithPresentingViewController:(nullable UIViewController *)presentingViewController presentedViewController:(nullable UIViewController *)presentedViewController animated:(BOOL)animated; - -@end +// +//#import +//#import +//#import +// +//@interface MVMCorePresentViewControllerOperation : MVMCoreOperation +// +//@property (nullable, weak, nonatomic) NSObject *delegate; +// +//- (nullable instancetype)initWithPresentingViewController:(nullable UIViewController *)presentingViewController presentedViewController:(nullable UIViewController *)presentedViewController animated:(BOOL)animated; +// +//@end diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCorePresentViewControllerOperation.m b/MVMCore/MVMCore/PresentationHandling/MVMCorePresentViewControllerOperation.m index 6b7c51b..fc65e88 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCorePresentViewControllerOperation.m +++ b/MVMCore/MVMCore/PresentationHandling/MVMCorePresentViewControllerOperation.m @@ -5,119 +5,119 @@ // Created by Scott Pfeil on 9/28/15. // Copyright © 2015 Verizon Wireless. All rights reserved. // - -#import "MVMCorePresentViewControllerOperation.h" -#import "MVMCoreAlertController.h" -#import "MVMCorePresentAnimationOperation.h" -#import "MVMCoreDispatchUtility.h" -#import "MVMCoreConstants.h" - -@interface MVMCorePresentViewControllerOperation () - -@property (nullable, strong, nonatomic) UIViewController *presentingViewController; -@property (nullable, strong, nonatomic) UIViewController *presentedViewController; -@property (nonatomic) BOOL animate; - -@property (nonatomic) BOOL beingObserved; -@property (nullable, weak, nonatomic) MVMCoreAlertController *alertController; - -@end - -@implementation MVMCorePresentViewControllerOperation - -// The context for kvo -static void * XXContext = &XXContext; - -- (void)dealloc { - [self stopObservingAlertView]; -} - -- (nullable instancetype)initWithPresentingViewController:(nullable UIViewController *)presentingViewController presentedViewController:(nullable UIViewController *)presentedViewController animated:(BOOL)animated { - - if (self = [super init]) { - self.presentedViewController = presentedViewController; - self.presentingViewController = presentingViewController; - self.animate = animated; - } - return self; -} - -- (void)main { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - // Always check for cancellation before launching the task. - if ([self checkAndHandleForCancellation]) { - return; - } - - [self present]; - }]; -} - -- (void)present { - - if ([self checkAndHandleForCancellation]) { - return; - } - - if (self.presentingViewController && self.presentedViewController) { - - // Gets the top most presented. - UIViewController *controllerToPresentOn = self.presentingViewController; - while (controllerToPresentOn.presentedViewController) { - controllerToPresentOn = controllerToPresentOn.presentedViewController; - } - - // If an alert is showing, don't present until the alerts are dismissed. - if ([controllerToPresentOn isKindOfClass:[MVMCoreAlertController class]]) { - [self observeForAlertDismissal:(MVMCoreAlertController *)controllerToPresentOn]; - } else { - MVMCorePresentAnimationOperation *animationOperation = [[MVMCorePresentAnimationOperation alloc] initWithPresentingViewController:controllerToPresentOn presentedViewController:self.presentedViewController animated:self.animate]; - animationOperation.delegate = self.delegate; - [animationOperation setCompletionBlock:^{ - [self markAsFinished]; - // Notify that page has changed - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:MVMCoreNotificationViewControllerChanged object:nil]; - }); - }]; - [[NSOperationQueue mainQueue] addOperation:animationOperation]; - } - } else { - [self markAsFinished]; - } -} - -- (void)cancel { - [super cancel]; - [self stopObservingAlertView]; -} - -#pragma mark - Observer Functions - -- (void)observeForAlertDismissal:(MVMCoreAlertController *)alertController { - if (!self.beingObserved) { - self.beingObserved = YES; - self.alertController = alertController; - [alertController addObserver:self forKeyPath:@"visible" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:XXContext]; - } -} - -- (void)stopObservingAlertView { - if (self.beingObserved) { - [self.alertController removeObserver:self forKeyPath:@"visible" context:XXContext]; - self.alertController = nil; - self.beingObserved = NO; - } -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - - if (context == XXContext && [keyPath isEqualToString:@"visible"]) { - if (![object isVisible]) { - [self stopObservingAlertView]; - [self present]; - } - } -} - -@end +// +//#import "MVMCorePresentViewControllerOperation.h" +//#import "MVMCoreAlertController.h" +//#import "MVMCorePresentAnimationOperation.h" +//#import "MVMCoreDispatchUtility.h" +//#import "MVMCoreConstants.h" +// +//@interface MVMCorePresentViewControllerOperation () +// +//@property (nullable, strong, nonatomic) UIViewController *presentingViewController; +//@property (nullable, strong, nonatomic) UIViewController *presentedViewController; +//@property (nonatomic) BOOL animate; +// +//@property (nonatomic) BOOL beingObserved; +//@property (nullable, weak, nonatomic) MVMCoreAlertController *alertController; +// +//@end +// +//@implementation MVMCorePresentViewControllerOperation +// +//// The context for kvo +//static void * XXContext = &XXContext; +// +//- (void)dealloc { +// [self stopObservingAlertView]; +//} +// +//- (nullable instancetype)initWithPresentingViewController:(nullable UIViewController *)presentingViewController presentedViewController:(nullable UIViewController *)presentedViewController animated:(BOOL)animated { +// +// if (self = [super init]) { +// self.presentedViewController = presentedViewController; +// self.presentingViewController = presentingViewController; +// self.animate = animated; +// } +// return self; +//} +// +//- (void)main { +// [MVMCoreDispatchUtility performBlockOnMainThread:^{ +// // Always check for cancellation before launching the task. +// if ([self checkAndHandleForCancellation]) { +// return; +// } +// +// [self present]; +// }]; +//} +// +//- (void)present { +// +// if ([self checkAndHandleForCancellation]) { +// return; +// } +// +// if (self.presentingViewController && self.presentedViewController) { +// +// // Gets the top most presented. +// UIViewController *controllerToPresentOn = self.presentingViewController; +// while (controllerToPresentOn.presentedViewController) { +// controllerToPresentOn = controllerToPresentOn.presentedViewController; +// } +// +// // If an alert is showing, don't present until the alerts are dismissed. +// if ([controllerToPresentOn isKindOfClass:[MVMCoreAlertController class]]) { +// [self observeForAlertDismissal:(MVMCoreAlertController *)controllerToPresentOn]; +// } else { +// MVMCorePresentAnimationOperation *animationOperation = [[MVMCorePresentAnimationOperation alloc] initWithPresentingViewController:controllerToPresentOn presentedViewController:self.presentedViewController animated:self.animate]; +// animationOperation.delegate = self.delegate; +// [animationOperation setCompletionBlock:^{ +// [self markAsFinished]; +// // Notify that page has changed +// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ +// [[NSNotificationCenter defaultCenter] postNotificationName:MVMCoreNotificationViewControllerChanged object:nil]; +// }); +// }]; +// [[NSOperationQueue mainQueue] addOperation:animationOperation]; +// } +// } else { +// [self markAsFinished]; +// } +//} +// +//- (void)cancel { +// [super cancel]; +// [self stopObservingAlertView]; +//} +// +//#pragma mark - Observer Functions +// +//- (void)observeForAlertDismissal:(MVMCoreAlertController *)alertController { +// if (!self.beingObserved) { +// self.beingObserved = YES; +// self.alertController = alertController; +// [alertController addObserver:self forKeyPath:@"visible" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:XXContext]; +// } +//} +// +//- (void)stopObservingAlertView { +// if (self.beingObserved) { +// [self.alertController removeObserver:self forKeyPath:@"visible" context:XXContext]; +// self.alertController = nil; +// self.beingObserved = NO; +// } +//} +// +//- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { +// +// if (context == XXContext && [keyPath isEqualToString:@"visible"]) { +// if (![object isVisible]) { +// [self stopObservingAlertView]; +// [self present]; +// } +// } +//} +// +//@end