diff --git a/MVMCore/MVMCore.xcodeproj/project.pbxproj b/MVMCore/MVMCore.xcodeproj/project.pbxproj index b73a67e..fc302b5 100644 --- a/MVMCore/MVMCore.xcodeproj/project.pbxproj +++ b/MVMCore/MVMCore.xcodeproj/project.pbxproj @@ -40,6 +40,8 @@ 8876D5F51FB50AB000EB2E3D /* UILabel+MFCustom.m in Sources */ = {isa = PBXBuildFile; fileRef = 8876D5E71FB50AB000EB2E3D /* UILabel+MFCustom.m */; }; 88D1FBE11FCCCBA100338A3A /* MVMCoreMainSplitViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 88D1FBDF1FCCCADC00338A3A /* MVMCoreMainSplitViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 88D1FBE21FCCCBA500338A3A /* PanelProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 88D1FBE01FCCCB2C00338A3A /* PanelProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A332F33F20C7231700DCD9D9 /* MVMCoreViewControllerAnimatedTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = A332F33E20C7231600DCD9D9 /* MVMCoreViewControllerAnimatedTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AF1201832108C9B400E2F592 /* MVMCoreViewManagerViewControllerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = AF1201812108C9B400E2F592 /* MVMCoreViewManagerViewControllerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; AF26DDAE1FCE6A37004E8F65 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = AF26DDB01FCE6A37004E8F65 /* Localizable.strings */; }; AF43A5771FBA5B7C008E9347 /* MVMCoreJSONConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = AF43A5751FBA5B7C008E9347 /* MVMCoreJSONConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; AF43A5781FBA5B7C008E9347 /* MVMCoreJSONConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = AF43A5761FBA5B7C008E9347 /* MVMCoreJSONConstants.m */; }; @@ -165,6 +167,8 @@ 8876D5E71FB50AB000EB2E3D /* UILabel+MFCustom.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UILabel+MFCustom.m"; sourceTree = ""; }; 88D1FBDF1FCCCADC00338A3A /* MVMCoreMainSplitViewProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreMainSplitViewProtocol.h; sourceTree = ""; }; 88D1FBE01FCCCB2C00338A3A /* PanelProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PanelProtocol.h; sourceTree = ""; }; + A332F33E20C7231600DCD9D9 /* MVMCoreViewControllerAnimatedTransitioning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreViewControllerAnimatedTransitioning.h; sourceTree = ""; }; + AF1201812108C9B400E2F592 /* MVMCoreViewManagerViewControllerProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreViewManagerViewControllerProtocol.h; sourceTree = ""; }; AF26DDAF1FCE6A37004E8F65 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; AF43A5751FBA5B7C008E9347 /* MVMCoreJSONConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreJSONConstants.h; sourceTree = ""; }; AF43A5761FBA5B7C008E9347 /* MVMCoreJSONConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreJSONConstants.m; sourceTree = ""; }; @@ -397,6 +401,7 @@ children = ( AF43A71A1FC5BEBB008E9347 /* MVMCoreViewControllerProtocol.h */, AF43A71F1FC5D2BA008E9347 /* MVMCoreViewManagerProtocol.h */, + AF1201812108C9B400E2F592 /* MVMCoreViewManagerViewControllerProtocol.h */, AF43A7401FC5FA6F008E9347 /* MVMCoreViewProtocol.h */, AFEEE8181FCDDE6B00B5EDD0 /* MVMCoreLoggingDelegateProtocol.h */, AF43A7001FC4B227008E9347 /* MVMCoreGlobalLoadProtocol.h */, @@ -486,6 +491,7 @@ AFBB96771FBA3A9A0008D868 /* MVMCorePresentationDelegateProtocol.h */, AFBB96781FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.h */, AFBB96791FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.m */, + A332F33E20C7231600DCD9D9 /* MVMCoreViewControllerAnimatedTransitioning.h */, ); path = PresentationHandling; sourceTree = ""; @@ -608,6 +614,7 @@ AFBB968F1FBA3A9A0008D868 /* MVMCoreNavigationObject.h in Headers */, 8876D5EC1FB50AB000EB2E3D /* NSDictionary+MFConvenience.h in Headers */, AFFCFA651FCCC0D700FD0730 /* MVMCoreLoadingOverlayDelegateProtocol.h in Headers */, + AF1201832108C9B400E2F592 /* MVMCoreViewManagerViewControllerProtocol.h in Headers */, AFBB96A31FBA3A9A0008D868 /* MVMCoreTopAlertObject.h in Headers */, AFBB96981FBA3A9A0008D868 /* MVMCoreAlertController.h in Headers */, 881D26961FCC9D180079C521 /* MVMCoreOperation.h in Headers */, @@ -616,6 +623,7 @@ 881D26951FCC9D180079C521 /* MVMCoreErrorObject.h in Headers */, AFBB96341FBA34310008D868 /* MVMCoreErrorConstants.h in Headers */, 88D1FBE21FCCCBA500338A3A /* PanelProtocol.h in Headers */, + A332F33F20C7231700DCD9D9 /* MVMCoreViewControllerAnimatedTransitioning.h in Headers */, AFBB968D1FBA3A9A0008D868 /* MVMCoreNavigationHandler.h in Headers */, AFBB96A51FBA3A9A0008D868 /* MVMCoreTopAlertOperation.h in Headers */, AFBB96A11FBA3A9A0008D868 /* MVMCoreTopAlertAnimationDelegateProtocol.h in Headers */, diff --git a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadRequestOperation.m b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadRequestOperation.m index b01a990..7f00738 100644 --- a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadRequestOperation.m +++ b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadRequestOperation.m @@ -880,6 +880,14 @@ } } +- (nullable id )navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id)animationController { + if (self.delegate && [self.delegate respondsToSelector:@selector(navigationController:interactionControllerForAnimationController:)]) { + return [self.delegate navigationController:navigationController interactionControllerForAnimationController:animationController]; + } else { + return nil; + } +} + - (void)viewController:(UIViewController *)presentingViewController willPresentViewController:(UIViewController *)presentedViewController { if ([self.delegate respondsToSelector:@selector(viewController:willPresentViewController:)]) { diff --git a/MVMCore/MVMCore/MVMCore.h b/MVMCore/MVMCore/MVMCore.h index e3402cf..2fd8fae 100644 --- a/MVMCore/MVMCore/MVMCore.h +++ b/MVMCore/MVMCore/MVMCore.h @@ -77,6 +77,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreVersionString[]; #import #import #import +#import // Action Handling #import @@ -87,6 +88,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreVersionString[]; // Protocols #import #import +#import #import #import diff --git a/MVMCore/MVMCore/MainProtocols/MVMCoreViewManagerProtocol.h b/MVMCore/MVMCore/MainProtocols/MVMCoreViewManagerProtocol.h index a3609e6..b9ab523 100644 --- a/MVMCore/MVMCore/MainProtocols/MVMCoreViewManagerProtocol.h +++ b/MVMCore/MVMCore/MainProtocols/MVMCoreViewManagerProtocol.h @@ -5,6 +5,7 @@ // Created by Pfeil, Scott Robert on 11/22/17. // Copyright © 2017 myverizon. All rights reserved. // +// A protocol for custom view managers. #import diff --git a/MVMCore/MVMCore/MainProtocols/MVMCoreViewManagerViewControllerProtocol.h b/MVMCore/MVMCore/MainProtocols/MVMCoreViewManagerViewControllerProtocol.h new file mode 100644 index 0000000..962a689 --- /dev/null +++ b/MVMCore/MVMCore/MainProtocols/MVMCoreViewManagerViewControllerProtocol.h @@ -0,0 +1,23 @@ +// +// MVMCoreViewManagerViewControllerProtocol.h +// MVMCore +// +// Created by Pfeil, Scott Robert on 7/25/18. +// Copyright © 2018 myverizon. All rights reserved. +// +// A protocol for view controllers that can be added to a view manager. + +#import + +@protocol MVMCoreViewManagerViewControllerProtocol + +@optional + +// Notifies the view controller that it can be ready (usually means that it's committed to the screen). +- (void)viewControllerReadyInManager:(nonnull NSObject *)manager; + +// Notifies the current showing view controller that the manager is disappearing. +- (void)managerWillDisappear:(nonnull NSObject *)manager; + +@end + diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m index a1fda67..a7e637d 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreNavigationOperation.m @@ -12,6 +12,7 @@ #import "MVMCoreViewControllerProtocol.h" #import "MVMCoreLoggingHandler.h" #import "MVMCoreLoadingOverlayHandler.h" +#import "MVMCoreViewControllerAnimatedTransitioning.h" @interface MVMCoreNavigationOperation () @@ -240,10 +241,39 @@ - (nullable id )navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC { if (self.delegate && [self.delegate respondsToSelector:@selector(navigationController:animationControllerForOperation:fromViewController:toViewController:)]) { - return [self.delegate navigationController:navigationController animationControllerForOperation:operation fromViewController:fromVC toViewController:toVC]; + id animatedTransitioning = [self.delegate navigationController:navigationController animationControllerForOperation:operation fromViewController:fromVC toViewController:toVC]; + if ([animatedTransitioning conformsToProtocol:@protocol(MVMCoreViewControllerAnimatedTransitioning)]) { + [animatedTransitioning addObserver:self forKeyPath:@"interactiveTransitionCanceled" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil]; + } + return animatedTransitioning; } else { return nil; } } +- (nullable id )navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id)animationController { + if (self.delegate && [self.delegate respondsToSelector:@selector(navigationController:interactionControllerForAnimationController:)]) { + return [self.delegate navigationController:navigationController interactionControllerForAnimationController:animationController]; + } else { + return nil; + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if ([keyPath isEqualToString:@"interactiveTransitionCanceled"]) { + [object removeObserver:self forKeyPath:@"interactiveTransitionCanceled"]; + BOOL transitionCanceled = ((NSNumber *)change[NSKeyValueChangeNewKey]).boolValue; + if (transitionCanceled) { + //When interactive transition canceled, the destination viewController should be removed from navigationController + [self.navigationObject.viewController removeFromParentViewController]; + [self markAsFinished]; + if (self.delegate && [self.delegate respondsToSelector:@selector(navigationController:interactiveTransitionWasCanceled:)]) { + [self.delegate navigationController:self.navigationObject.navigationController interactiveTransitionWasCanceled:true]; + } + } + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + @end diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCorePresentationDelegateProtocol.h b/MVMCore/MVMCore/PresentationHandling/MVMCorePresentationDelegateProtocol.h index 219abd8..8dc27f4 100644 --- a/MVMCore/MVMCore/PresentationHandling/MVMCorePresentationDelegateProtocol.h +++ b/MVMCore/MVMCore/PresentationHandling/MVMCorePresentationDelegateProtocol.h @@ -19,11 +19,18 @@ // Called when a view controller has been displayed on a navigation controller - (void)navigationController:(nonnull UINavigationController *)navigationController displayedViewController:(nonnull UIViewController *)viewController; +// Called when interactive transition get canceled +- (void)navigationController:(nonnull UINavigationController *)navigationController interactiveTransitionWasCanceled:(BOOL)canceled; + + - (nullable id )navigationController:(nonnull UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(nonnull UIViewController *)fromVC toViewController:(nonnull UIViewController *)toVC NS_AVAILABLE_IOS(7_0); +- (nullable id )navigationController:(nonnull UINavigationController *)navigationController + interactionControllerForAnimationController:(nonnull id ) animationController NS_AVAILABLE_IOS(7_0); + // Called when a view controller will be presented on another view controller - (void)viewController:(nonnull UIViewController *)presentingViewController willPresentViewController:(nonnull UIViewController *)presentedViewController; diff --git a/MVMCore/MVMCore/PresentationHandling/MVMCoreViewControllerAnimatedTransitioning.h b/MVMCore/MVMCore/PresentationHandling/MVMCoreViewControllerAnimatedTransitioning.h new file mode 100644 index 0000000..c5fc952 --- /dev/null +++ b/MVMCore/MVMCore/PresentationHandling/MVMCoreViewControllerAnimatedTransitioning.h @@ -0,0 +1,17 @@ +// +// MVMCoreViewControllerAnimatedTransitioning.h +// MVMCore +// +// Created by Chen, Mingyuan on 6/5/18. +// Copyright © 2018 myverizon. All rights reserved. +// + +#import + +@protocol MVMCoreViewControllerAnimatedTransitioning + +@required + +@property (nonatomic) BOOL interactiveTransitionCanceled; + +@end