From 060b6b330348c6785426a70797d802d5a9117ad0 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 3 May 2018 14:18:18 -0400 Subject: [PATCH 1/4] Queueing alerts --- MVMCore/MVMCore.xcodeproj/project.pbxproj | 8 ++++ MVMCore/MVMCore/MVMCore.h | 1 + .../MVMCoreNavigationHandler.h | 4 ++ .../MVMCoreNavigationHandler.m | 7 +++- .../MVMCore/Utility/MVMCoreBlockOperation.h | 16 ++++++++ .../MVMCore/Utility/MVMCoreBlockOperation.m | 37 +++++++++++++++++++ 6 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 MVMCore/MVMCore/Utility/MVMCoreBlockOperation.h create mode 100644 MVMCore/MVMCore/Utility/MVMCoreBlockOperation.m diff --git a/MVMCore/MVMCore.xcodeproj/project.pbxproj b/MVMCore/MVMCore.xcodeproj/project.pbxproj index 6845002..f1d48bc 100644 --- a/MVMCore/MVMCore.xcodeproj/project.pbxproj +++ b/MVMCore/MVMCore.xcodeproj/project.pbxproj @@ -123,6 +123,8 @@ AFBB96ED1FBA4A260008D868 /* MFHardCodedServerResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96EA1FBA4A260008D868 /* MFHardCodedServerResponse.m */; }; AFC5FA161FFC2E2A00C244CF /* MVMCoreGlobalTopAlertDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = AFC5FA141FFC2E2A00C244CF /* MVMCoreGlobalTopAlertDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; AFC5FA1D1FFC39C700C244CF /* MVMCoreTopAlertViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = AFC5FA1C1FFC39C700C244CF /* MVMCoreTopAlertViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AFEA17A8209B6A1C00BC6740 /* MVMCoreBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AFEA17A6209B6A1C00BC6740 /* MVMCoreBlockOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AFEA17A9209B6A1C00BC6740 /* MVMCoreBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AFEA17A7209B6A1C00BC6740 /* MVMCoreBlockOperation.m */; }; AFED77A11FCCA29400BAE689 /* MVMCoreViewControllerNibMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = AFED77991FCCA29300BAE689 /* MVMCoreViewControllerNibMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; AFED77A21FCCA29400BAE689 /* MVMCoreViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = AFED779A1FCCA29300BAE689 /* MVMCoreViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; AFED77A31FCCA29400BAE689 /* MVMCoreViewControllerNibMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = AFED779B1FCCA29300BAE689 /* MVMCoreViewControllerNibMappingObject.m */; }; @@ -251,6 +253,8 @@ AFBB96EA1FBA4A260008D868 /* MFHardCodedServerResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFHardCodedServerResponse.m; sourceTree = ""; }; AFC5FA141FFC2E2A00C244CF /* MVMCoreGlobalTopAlertDelegateProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreGlobalTopAlertDelegateProtocol.h; sourceTree = ""; }; AFC5FA1C1FFC39C700C244CF /* MVMCoreTopAlertViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreTopAlertViewProtocol.h; sourceTree = ""; }; + AFEA17A6209B6A1C00BC6740 /* MVMCoreBlockOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreBlockOperation.h; sourceTree = ""; }; + AFEA17A7209B6A1C00BC6740 /* MVMCoreBlockOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreBlockOperation.m; sourceTree = ""; }; AFED77991FCCA29300BAE689 /* MVMCoreViewControllerNibMappingObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreViewControllerNibMappingObject.h; sourceTree = ""; }; AFED779A1FCCA29300BAE689 /* MVMCoreViewControllerMappingObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreViewControllerMappingObject.h; sourceTree = ""; }; AFED779B1FCCA29300BAE689 /* MVMCoreViewControllerNibMappingObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreViewControllerNibMappingObject.m; sourceTree = ""; }; @@ -327,6 +331,8 @@ 881D268F1FCC9D180079C521 /* MVMCoreErrorObject.m */, 881D26921FCC9D180079C521 /* MVMCoreOperation.h */, 881D26901FCC9D180079C521 /* MVMCoreOperation.m */, + AFEA17A6209B6A1C00BC6740 /* MVMCoreBlockOperation.h */, + AFEA17A7209B6A1C00BC6740 /* MVMCoreBlockOperation.m */, AFBB96E71FBA4A260008D868 /* HardCodedServerResponse */, AFBB96AB1FBA3B590008D868 /* Helpers */, ); @@ -647,6 +653,7 @@ AFBB968B1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.h in Headers */, AF43A70B1FC4F415008E9347 /* MVMCoreCache.h in Headers */, AFBB965C1FBA3A570008D868 /* MFFreebeeHandler.h in Headers */, + AFEA17A8209B6A1C00BC6740 /* MVMCoreBlockOperation.h in Headers */, AF43A5831FBB66DE008E9347 /* MVMCoreConstants.h in Headers */, AFBB969A1FBA3A9A0008D868 /* MVMCoreAlertDelegateProtocol.h in Headers */, AFED77A81FCCA29400BAE689 /* MVMCoreViewControllerStoryBoardMappingObject.h in Headers */, @@ -795,6 +802,7 @@ AF43A7071FC4D7A2008E9347 /* MVMCoreObject.m in Sources */, AFBB96B11FBA3B590008D868 /* MVMCoreDispatchUtility.m in Sources */, AFBB965B1FBA3A570008D868 /* FreeBeeUrlObject.m in Sources */, + AFEA17A9209B6A1C00BC6740 /* MVMCoreBlockOperation.m in Sources */, AF43A70A1FC4F415008E9347 /* MVMCoreCache.m in Sources */, AF43A6FF1FBE3252008E9347 /* Reachability.m in Sources */, AFBB96921FBA3A9A0008D868 /* MVMCoreNavigationOperation.m in Sources */, diff --git a/MVMCore/MVMCore/MVMCore.h b/MVMCore/MVMCore/MVMCore.h index 923a1bc..e3402cf 100644 --- a/MVMCore/MVMCore/MVMCore.h +++ b/MVMCore/MVMCore/MVMCore.h @@ -35,6 +35,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreVersionString[]; #import #import #import +#import // Mapping #import diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.h b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.h index a3e5bcd..32789d0 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.h +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.h @@ -10,6 +10,7 @@ #import #import +@class MVMCoreOperation; @class MVMCoreNavigationObject; @class MVMCoreLoadObject; @@ -67,6 +68,9 @@ // Use this to pop to the root of the stack. - (void)popToRootAnimated:(BOOL)animated; +// Adds the navigation operation to the queue. +- (void)addNavigationOperation:(nonnull MVMCoreOperation *)operation; + // Removes all queued up items. - (void)cancelNavigation; diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.m b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.m index 727d97b..4f89c71 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.m +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.m @@ -165,7 +165,12 @@ - (void)popToRootAnimated:(BOOL)animated { MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:nil viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopToRoot]; - [self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];} + [self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL]; +} + +- (void)addNavigationOperation:(nonnull MVMCoreOperation *)operation { + [self.navigationQueue addOperation:operation]; +} - (void)cancelNavigation { [self.navigationQueue cancelAllOperations]; diff --git a/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.h b/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.h new file mode 100644 index 0000000..5096a20 --- /dev/null +++ b/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.h @@ -0,0 +1,16 @@ +// +// MVMCoreBlockOperation.h +// MVMCore +// +// Created by Pfeil, Scott Robert on 5/3/18. +// Copyright © 2018 myverizon. All rights reserved. +// + +#import + +@interface MVMCoreBlockOperation : MVMCoreOperation + +// Start this operation with the block. This block needs to call mark as finished when finished. ++ (nullable instancetype)blockOperationWithBlock:(nonnull void (^)(MVMCoreBlockOperation * _Nonnull operation))block; + +@end diff --git a/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.m b/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.m new file mode 100644 index 0000000..85a223a --- /dev/null +++ b/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.m @@ -0,0 +1,37 @@ +// +// MVMCoreBlockOperation.m +// MVMCore +// +// Created by Pfeil, Scott Robert on 5/3/18. +// Copyright © 2018 myverizon. All rights reserved. +// + +#import "MVMCoreBlockOperation.h" + +@interface MVMCoreBlockOperation () + +@property (nonatomic, copy) void (^block)(MVMCoreBlockOperation * _Nonnull operation); + +@end + +@implementation MVMCoreBlockOperation + ++ (nullable instancetype)blockOperationWithBlock:(nonnull void (^)(MVMCoreBlockOperation * _Nonnull operation))block { + MVMCoreBlockOperation *operation = [[MVMCoreBlockOperation alloc] init]; + operation.block = block; + return operation; +} + + +- (void)main { + + // Always check for cancellation before launching the task. + if ([self checkAndHandleForCancellation]) { + return; + } + + __weak typeof(self) weakSelf = self; + self.block(weakSelf); +} + +@end From 50fb716f99215b586b471b5feea11ff481117783 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 7 May 2018 15:48:59 -0400 Subject: [PATCH 2/4] Top alert queue fix --- .../MVMCore/PresentationHandling/MVMCoreNavigationHandler.m | 5 +++++ .../MVMCore/PresentationHandling/MVMCoreNavigationObject.h | 1 + .../PresentationHandling/MVMCoreNavigationOperation.m | 6 +++++- MVMCore/MVMCore/Utility/MVMCoreBlockOperation.m | 1 - 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.m b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.m index 4f89c71..b6aa0aa 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.m +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationHandler.m @@ -16,6 +16,7 @@ #import "MVMCoreRequestParameters.h" #import "MVMCoreErrorConstants.h" #import "MVMCoreLoggingHandler.h" +#import "MVMCoreLoadingOverlayHandler.h" @interface MVMCoreNavigationHandler () @@ -90,6 +91,10 @@ - (void)startNavigationWithNavigationObject:(MVMCoreNavigationObject *)navigationObject delegate:(nullable NSObject*)delegate completionHandler:(nullable void (^)(void))completionBlock { + // In case it takes some time to happen. + [[MVMCoreLoadingOverlayHandler sharedLoadingOverlay] startLoading]; + navigationObject.stopLoadingOverlay = YES; + MVMCoreNavigationOperation *navigationOperation = [[MVMCoreNavigationOperation alloc] initWithNavigationObject:navigationObject]; navigationOperation.delegate = delegate; navigationOperation.completionBlock = completionBlock; diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationObject.h b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationObject.h index 71e7c72..527110f 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationObject.h +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationObject.h @@ -20,6 +20,7 @@ @property (nonatomic) NavigationType navigationType; @property (nonatomic) BOOL animated; @property (nonatomic) BOOL tryToReplaceFirst; +@property (nonatomic) BOOL stopLoadingOverlay; - (nullable instancetype)initWithViewController:(nullable UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController viewControllers:(nullable NSArray *)viewControllers animated:(BOOL)animated tryToReplaceFirst:(BOOL)tryToReplaceFirst navigationType:(NavigationType)navigationType; diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m index 45d8647..19f2743 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m @@ -11,6 +11,7 @@ #import "MVMCoreViewManagerProtocol.h" #import "MVMCoreViewControllerProtocol.h" #import "MVMCoreLoggingHandler.h" +#import "MVMCoreLoadingOverlayHandler.h" @interface MVMCoreNavigationOperation () @@ -209,7 +210,10 @@ } - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { - + if (self.navigationObject.stopLoadingOverlay) { + [[MVMCoreLoadingOverlayHandler sharedLoadingOverlay] stopLoading:YES]; + } + if (self.delegate && [self.delegate respondsToSelector:@selector(navigationController:willDisplayViewController:)]) { [self.delegate navigationController:navigationController willDisplayViewController:viewController]; } diff --git a/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.m b/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.m index 85a223a..f0fc8ce 100644 --- a/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.m +++ b/MVMCore/MVMCore/Utility/MVMCoreBlockOperation.m @@ -22,7 +22,6 @@ return operation; } - - (void)main { // Always check for cancellation before launching the task. From d91e8a836540f772d0ad48a1649adaf06f61779b Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 7 May 2018 16:12:39 -0400 Subject: [PATCH 3/4] to catch all scenarios --- .../PresentationHandling/MVMCoreNavigationOperation.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m index 19f2743..e53f5b2 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m @@ -206,12 +206,17 @@ - (void)markAsFinished { self.navigationObject.navigationController.delegate = nil; + if (self.navigationObject.stopLoadingOverlay) { + [[MVMCoreLoadingOverlayHandler sharedLoadingOverlay] stopLoading:YES]; + self.navigationObject.stopLoadingOverlay = NO; + } [super markAsFinished]; } - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { if (self.navigationObject.stopLoadingOverlay) { [[MVMCoreLoadingOverlayHandler sharedLoadingOverlay] stopLoading:YES]; + self.navigationObject.stopLoadingOverlay = NO; } if (self.delegate && [self.delegate respondsToSelector:@selector(navigationController:willDisplayViewController:)]) { @@ -225,7 +230,6 @@ [self.delegate navigationController:navigationController displayedViewController:viewController]; } [self markAsFinished]; - } - (nullable id )navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC { From 56c8a961eb1573091ea6da511a6aa24efd6a03c5 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 8 May 2018 11:26:32 -0400 Subject: [PATCH 4/4] fixing major navigation operation defect. dispatch after instead of nstimer --- .../AlertHandling/MVMCoreTopAlertOperation.m | 44 ++++--------------- .../MVMCoreNavigationOperation.m | 8 +++- 2 files changed, 16 insertions(+), 36 deletions(-) diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreTopAlertOperation.m b/MVMCore/MVMCore/AlertHandling/MVMCoreTopAlertOperation.m index a4cbfb8..222a56e 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreTopAlertOperation.m +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreTopAlertOperation.m @@ -16,22 +16,16 @@ __block BOOL _paused; __block BOOL _displayed; __block BOOL _animating; - __block NSTimer *_dismissTimer; } @property (readwrite, getter=isPaused) BOOL paused; - @property (readwrite, getter=isDisplayed) BOOL displayed; - @property (readwrite, getter=isAnimating) BOOL animating; -@property (strong, nonatomic) NSTimer *dismissTimer; - // For thread safety @property (strong, nonatomic) dispatch_queue_t pausedQueue; @property (strong, nonatomic) dispatch_queue_t displayedQueue; @property (strong, nonatomic) dispatch_queue_t animatingQueue; -@property (strong, nonatomic) dispatch_queue_t timerQueue; @end @@ -44,7 +38,6 @@ self.pausedQueue = dispatch_queue_create("paused", DISPATCH_QUEUE_CONCURRENT); self.displayedQueue = dispatch_queue_create("displayed", DISPATCH_QUEUE_CONCURRENT); self.animatingQueue = dispatch_queue_create("animating", DISPATCH_QUEUE_CONCURRENT); - self.timerQueue = dispatch_queue_create("timer", DISPATCH_QUEUE_CONCURRENT); } return self; } @@ -102,20 +95,6 @@ }); } -- (NSTimer *)dismissTimer { - __block NSTimer *timer; - dispatch_sync(self.timerQueue, ^{ - timer = _dismissTimer; - }); - return timer; -} - -- (void)setDismissTimer:(NSTimer *)dismissTimer { - dispatch_barrier_async(self.timerQueue, ^{ - _dismissTimer = dismissTimer; - }); -} - - (void)main { // Always check for cancellation before launching the task. @@ -156,7 +135,14 @@ } else { dismissTime = TopAlertDismissTime; } - self.dismissTimer = [NSTimer scheduledTimerWithTimeInterval:dismissTime target:self selector:@selector(timerFinished) userInfo:nil repeats:NO]; + + __weak typeof(self) weakSelf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(dismissTime * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + if (weakSelf.isFinished || [weakSelf checkAndHandleForCancellation]) { + return; + } + [weakSelf dismissAlertView:YES]; + }); } }]; } @@ -166,19 +152,9 @@ } } -- (void)timerFinished { - [self dismissAlertView:YES]; -} - - (void)cancel { [super cancel]; - // Kill the dismiss timer. - if (self.dismissTimer) { - [self.dismissTimer invalidate]; - self.dismissTimer = nil; - } - // Do nothing if animating. if (!self.isAnimating) { @@ -191,9 +167,7 @@ } - (void)dismissAlertView:(BOOL)andFinish { - - self.dismissTimer = nil; - + if (self.isDisplayed && !self.isAnimating) { // Dismisses. diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m index e53f5b2..a1fda67 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m @@ -134,6 +134,8 @@ { if (self.navigationObject.navigationController.viewControllers.count > 1) { [self.navigationObject.navigationController popViewControllerAnimated:self.navigationObject.animated]; + } else { + [self markAsFinished]; } } break; @@ -182,7 +184,11 @@ break; case NavigationTypePopToRoot: { - [self.navigationObject.navigationController popToRootViewControllerAnimated:self.navigationObject.animated]; + if (self.navigationObject.navigationController.viewControllers.count > 1) { + [self.navigationObject.navigationController popToRootViewControllerAnimated:self.navigationObject.animated]; + } else { + [self markAsFinished]; + } } break; default: