Swiftification of Navigation Handler
This commit is contained in:
parent
2300678d96
commit
a4e0203de5
@ -95,6 +95,8 @@
|
||||
AF43A74D1FC6109F008E9347 /* MVMCoreSessionObject.m in Sources */ = {isa = PBXBuildFile; fileRef = AF43A74B1FC6109F008E9347 /* MVMCoreSessionObject.m */; };
|
||||
AF60A7F2289212CA00919EEB /* MVMError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF60A7F1289212CA00919EEB /* MVMError.swift */; };
|
||||
AF60A7F4289212EB00919EEB /* MVMCoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF60A7F3289212EB00919EEB /* MVMCoreError.swift */; };
|
||||
AF686FDA2A8A876A008F666A /* NavigationOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF686FD92A8A876A008F666A /* NavigationOperation.swift */; };
|
||||
AF686FDC2A8A87EA008F666A /* KVOPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF686FDB2A8A87EA008F666A /* KVOPublisher.swift */; };
|
||||
AF69D4E9286E54D500BC6862 /* ActionCallHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF69D4E8286E54D500BC6862 /* ActionCallHandler.swift */; };
|
||||
AF69D4EB286E586200BC6862 /* ActionRestartHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF69D4EA286E586200BC6862 /* ActionRestartHandler.swift */; };
|
||||
AF69D4ED286E5D8C00BC6862 /* ActionCancelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF69D4EC286E5D8C00BC6862 /* ActionCancelHandler.swift */; };
|
||||
@ -108,12 +110,8 @@
|
||||
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 /* NavigationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF925DED28BD35A2008E8677 /* NavigationHandler.swift */; };
|
||||
AFA4931E29E5C988001A9663 /* MVMCoreActionUtility+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4931D29E5C988001A9663 /* MVMCoreActionUtility+Extension.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, ); }; };
|
||||
@ -125,19 +123,7 @@
|
||||
AFBB96641FBA3A570008D868 /* MVMCoreLoadHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB964B1FBA3A560008D868 /* MVMCoreLoadHandler.m */; };
|
||||
AFBB96691FBA3A570008D868 /* MVMCoreRequestParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96511FBA3A560008D868 /* MVMCoreRequestParameters.m */; };
|
||||
AFBB966A1FBA3A570008D868 /* MVMCoreLoadRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96521FBA3A570008D868 /* MVMCoreLoadRequestOperation.m */; };
|
||||
AFBB968B1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB966D1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
AFBB968C1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB966E1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.m */; };
|
||||
AFBB968D1FBA3A9A0008D868 /* MVMCoreNavigationHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB966F1FBA3A9A0008D868 /* MVMCoreNavigationHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
AFBB968E1FBA3A9A0008D868 /* MVMCoreNavigationHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96701FBA3A9A0008D868 /* MVMCoreNavigationHandler.m */; };
|
||||
AFBB968F1FBA3A9A0008D868 /* MVMCoreNavigationObject.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB96711FBA3A9A0008D868 /* MVMCoreNavigationObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
AFBB96901FBA3A9A0008D868 /* MVMCoreNavigationObject.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96721FBA3A9A0008D868 /* MVMCoreNavigationObject.m */; };
|
||||
AFBB96911FBA3A9A0008D868 /* MVMCoreNavigationOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB96731FBA3A9A0008D868 /* MVMCoreNavigationOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
AFBB96921FBA3A9A0008D868 /* MVMCoreNavigationOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96741FBA3A9A0008D868 /* MVMCoreNavigationOperation.m */; };
|
||||
AFBB96931FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB96751FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
AFBB96941FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96761FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.m */; };
|
||||
AFBB96951FBA3A9A0008D868 /* MVMCorePresentationDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB96771FBA3A9A0008D868 /* MVMCorePresentationDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
AFBB96961FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB96781FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
AFBB96971FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96791FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.m */; };
|
||||
AFBB96B01FBA3B590008D868 /* MVMCoreDispatchUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB96AC1FBA3B590008D868 /* MVMCoreDispatchUtility.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
AFBB96B11FBA3B590008D868 /* MVMCoreDispatchUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = AFBB96AD1FBA3B590008D868 /* MVMCoreDispatchUtility.m */; };
|
||||
AFBB96B21FBA3B590008D868 /* MVMCoreGetterUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = AFBB96AE1FBA3B590008D868 /* MVMCoreGetterUtility.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -264,6 +250,8 @@
|
||||
AF43A74B1FC6109F008E9347 /* MVMCoreSessionObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreSessionObject.m; sourceTree = "<group>"; };
|
||||
AF60A7F1289212CA00919EEB /* MVMError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMError.swift; sourceTree = "<group>"; };
|
||||
AF60A7F3289212EB00919EEB /* MVMCoreError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreError.swift; sourceTree = "<group>"; };
|
||||
AF686FD92A8A876A008F666A /* NavigationOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationOperation.swift; sourceTree = "<group>"; };
|
||||
AF686FDB2A8A87EA008F666A /* KVOPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KVOPublisher.swift; sourceTree = "<group>"; };
|
||||
AF69D4E8286E54D500BC6862 /* ActionCallHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionCallHandler.swift; sourceTree = "<group>"; };
|
||||
AF69D4EA286E586200BC6862 /* ActionRestartHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionRestartHandler.swift; sourceTree = "<group>"; };
|
||||
AF69D4EC286E5D8C00BC6862 /* ActionCancelHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionCancelHandler.swift; sourceTree = "<group>"; };
|
||||
@ -277,12 +265,8 @@
|
||||
AF70699F2880F0EB00077CF6 /* ActionOpenPageHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionOpenPageHandler.swift; sourceTree = "<group>"; };
|
||||
AF787412286DEF8B00670588 /* ActionBackHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionBackHandler.swift; sourceTree = "<group>"; };
|
||||
AF8D13382774EA1D008AF4A9 /* ActionOpenUrlHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionOpenUrlHandler.swift; sourceTree = "<group>"; };
|
||||
AF925DED28BD35A2008E8677 /* NavigationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationHandler.swift; sourceTree = "<group>"; };
|
||||
AFA4931D29E5C988001A9663 /* MVMCoreActionUtility+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreActionUtility+Extension.swift"; sourceTree = "<group>"; };
|
||||
AF925DED28BD35A2008E8677 /* MVMCoreNavigationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationHandler.swift; sourceTree = "<group>"; };
|
||||
AF925DEF28BE78E2008E8677 /* MVMCoreNavigationPresentOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationPresentOperation.swift; sourceTree = "<group>"; };
|
||||
AF925DF328C0FA38008E8677 /* MVMCoreNavigationPushOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationPushOperation.swift; sourceTree = "<group>"; };
|
||||
AF925DF528C10732008E8677 /* MVMCoreNavigationSetOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationSetOperation.swift; sourceTree = "<group>"; };
|
||||
AF925DF728C10B00008E8677 /* MVMCoreNavigationPopOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreNavigationPopOperation.swift; sourceTree = "<group>"; };
|
||||
AFBB96321FBA34310008D868 /* MVMCoreErrorConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreErrorConstants.h; sourceTree = "<group>"; };
|
||||
AFBB96331FBA34310008D868 /* MVMCoreErrorConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreErrorConstants.m; sourceTree = "<group>"; };
|
||||
AFBB96371FBA39E70008D868 /* MVMCoreLoadDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreLoadDelegateProtocol.h; sourceTree = "<group>"; };
|
||||
@ -294,19 +278,7 @@
|
||||
AFBB964B1FBA3A560008D868 /* MVMCoreLoadHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreLoadHandler.m; sourceTree = "<group>"; };
|
||||
AFBB96511FBA3A560008D868 /* MVMCoreRequestParameters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreRequestParameters.m; sourceTree = "<group>"; };
|
||||
AFBB96521FBA3A570008D868 /* MVMCoreLoadRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreLoadRequestOperation.m; sourceTree = "<group>"; };
|
||||
AFBB966D1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreDismissViewControllerOperation.h; sourceTree = "<group>"; };
|
||||
AFBB966E1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreDismissViewControllerOperation.m; sourceTree = "<group>"; };
|
||||
AFBB966F1FBA3A9A0008D868 /* MVMCoreNavigationHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreNavigationHandler.h; sourceTree = "<group>"; };
|
||||
AFBB96701FBA3A9A0008D868 /* MVMCoreNavigationHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreNavigationHandler.m; sourceTree = "<group>"; };
|
||||
AFBB96711FBA3A9A0008D868 /* MVMCoreNavigationObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreNavigationObject.h; sourceTree = "<group>"; };
|
||||
AFBB96721FBA3A9A0008D868 /* MVMCoreNavigationObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreNavigationObject.m; sourceTree = "<group>"; };
|
||||
AFBB96731FBA3A9A0008D868 /* MVMCoreNavigationOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreNavigationOperation.h; sourceTree = "<group>"; };
|
||||
AFBB96741FBA3A9A0008D868 /* MVMCoreNavigationOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreNavigationOperation.m; sourceTree = "<group>"; };
|
||||
AFBB96751FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCorePresentAnimationOperation.h; sourceTree = "<group>"; };
|
||||
AFBB96761FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCorePresentAnimationOperation.m; sourceTree = "<group>"; };
|
||||
AFBB96771FBA3A9A0008D868 /* MVMCorePresentationDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCorePresentationDelegateProtocol.h; sourceTree = "<group>"; };
|
||||
AFBB96781FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCorePresentViewControllerOperation.h; sourceTree = "<group>"; };
|
||||
AFBB96791FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCorePresentViewControllerOperation.m; sourceTree = "<group>"; };
|
||||
AFBB96AC1FBA3B590008D868 /* MVMCoreDispatchUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreDispatchUtility.h; sourceTree = "<group>"; };
|
||||
AFBB96AD1FBA3B590008D868 /* MVMCoreDispatchUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreDispatchUtility.m; sourceTree = "<group>"; };
|
||||
AFBB96AE1FBA3B590008D868 /* MVMCoreGetterUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreGetterUtility.h; sourceTree = "<group>"; };
|
||||
@ -601,24 +573,9 @@
|
||||
AFBB966B1FBA3A9A0008D868 /* PresentationHandling */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
AFBB966D1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.h */,
|
||||
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 */,
|
||||
AF925DED28BD35A2008E8677 /* NavigationHandler.swift */,
|
||||
AF686FD92A8A876A008F666A /* NavigationOperation.swift */,
|
||||
AFBB96771FBA3A9A0008D868 /* MVMCorePresentationDelegateProtocol.h */,
|
||||
AFBB96781FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.h */,
|
||||
AFBB96791FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.m */,
|
||||
A332F33E20C7231600DCD9D9 /* MVMCoreViewControllerAnimatedTransitioning.h */,
|
||||
);
|
||||
path = PresentationHandling;
|
||||
@ -635,6 +592,7 @@
|
||||
AF43A5851FBB67D6008E9347 /* MVMCoreActionUtility.h */,
|
||||
AF43A5861FBB67D6008E9347 /* MVMCoreActionUtility.m */,
|
||||
AFA4931D29E5C988001A9663 /* MVMCoreActionUtility+Extension.swift */,
|
||||
AF686FDB2A8A87EA008F666A /* KVOPublisher.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
@ -753,10 +711,6 @@
|
||||
AFBB96EC1FBA4A260008D868 /* MFHardCodedServerResponse.h in Headers */,
|
||||
AFBB96B21FBA3B590008D868 /* MVMCoreGetterUtility.h in Headers */,
|
||||
8876D5F21FB50AB000EB2E3D /* UIFont+MFSpacing.h in Headers */,
|
||||
AFBB96931FBA3A9A0008D868 /* MVMCorePresentAnimationOperation.h in Headers */,
|
||||
AFBB96961FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.h in Headers */,
|
||||
AFBB96911FBA3A9A0008D868 /* MVMCoreNavigationOperation.h in Headers */,
|
||||
AFBB968F1FBA3A9A0008D868 /* MVMCoreNavigationObject.h in Headers */,
|
||||
8876D5EC1FB50AB000EB2E3D /* NSDictionary+MFConvenience.h in Headers */,
|
||||
AFFCFA651FCCC0D700FD0730 /* MVMCoreLoadingOverlayDelegateProtocol.h in Headers */,
|
||||
AF1201832108C9B400E2F592 /* MVMCoreViewManagerViewControllerProtocol.h in Headers */,
|
||||
@ -766,7 +720,6 @@
|
||||
881D26951FCC9D180079C521 /* MVMCoreErrorObject.h in Headers */,
|
||||
AFBB96341FBA34310008D868 /* MVMCoreErrorConstants.h in Headers */,
|
||||
A332F33F20C7231700DCD9D9 /* MVMCoreViewControllerAnimatedTransitioning.h in Headers */,
|
||||
AFBB968D1FBA3A9A0008D868 /* MVMCoreNavigationHandler.h in Headers */,
|
||||
AFBB96951FBA3A9A0008D868 /* MVMCorePresentationDelegateProtocol.h in Headers */,
|
||||
AFED77A51FCCA29400BAE689 /* MVMCoreViewControllerProgrammaticMappingObject.h in Headers */,
|
||||
AF43A5871FBB67D6008E9347 /* MVMCoreActionUtility.h in Headers */,
|
||||
@ -788,7 +741,6 @@
|
||||
8876D5CE1FB50A9E00EB2E3D /* MVMCore.h in Headers */,
|
||||
AF43A57B1FBA5E6A008E9347 /* MVMCoreHardcodedStringsConstants.h in Headers */,
|
||||
AFBB96B81FBA3CEC0008D868 /* MVMCoreActionDelegateProtocol.h in Headers */,
|
||||
AFBB968B1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.h in Headers */,
|
||||
AF43A70B1FC4F415008E9347 /* MVMCoreCache.h in Headers */,
|
||||
AFEA17A8209B6A1C00BC6740 /* MVMCoreBlockOperation.h in Headers */,
|
||||
AF43A5831FBB66DE008E9347 /* MVMCoreConstants.h in Headers */,
|
||||
@ -902,10 +854,9 @@
|
||||
AFBB96641FBA3A570008D868 /* MVMCoreLoadHandler.m in Sources */,
|
||||
AFFCFA671FCCC0D700FD0730 /* MVMCoreLoadingOverlayHandler.m in Sources */,
|
||||
AF8D13392774EA1D008AF4A9 /* ActionOpenUrlHandler.swift in Sources */,
|
||||
AF925DEE28BD35A2008E8677 /* MVMCoreNavigationHandler.swift in Sources */,
|
||||
AF925DEE28BD35A2008E8677 /* NavigationHandler.swift in Sources */,
|
||||
AF130B8E2788DF6E00C6C03C /* OpenURLOptionsModel.swift in Sources */,
|
||||
AF69D4EB286E586200BC6862 /* ActionRestartHandler.swift in Sources */,
|
||||
AFBB968E1FBA3A9A0008D868 /* MVMCoreNavigationHandler.m in Sources */,
|
||||
BB780ADF250F8C890030BD2F /* ActionNoopModel.swift in Sources */,
|
||||
D2E1FAD92260C3E400AEFD8C /* DelegateObject.swift in Sources */,
|
||||
01F2A03623A80A7300D954D8 /* ActionModelProtocol.swift in Sources */,
|
||||
@ -914,12 +865,10 @@
|
||||
01C851CF23CF7B260021F976 /* JSONMap.swift in Sources */,
|
||||
01F2A04C23A82B1B00D954D8 /* ActionCallModel.swift in Sources */,
|
||||
8876D5ED1FB50AB000EB2E3D /* NSDictionary+MFConvenience.m in Sources */,
|
||||
AFBB968C1FBA3A9A0008D868 /* MVMCoreDismissViewControllerOperation.m in Sources */,
|
||||
AF925DF628C10732008E8677 /* MVMCoreNavigationSetOperation.swift in Sources */,
|
||||
AF686FDA2A8A876A008F666A /* NavigationOperation.swift in Sources */,
|
||||
AFBB96ED1FBA4A260008D868 /* MFHardCodedServerResponse.m in Sources */,
|
||||
AF43A74D1FC6109F008E9347 /* MVMCoreSessionObject.m in Sources */,
|
||||
D282AAB62240085300C46919 /* MVMCoreGetterUtility+Extension.swift in Sources */,
|
||||
AFBB96901FBA3A9A0008D868 /* MVMCoreNavigationObject.m in Sources */,
|
||||
AFA4931E29E5C988001A9663 /* MVMCoreActionUtility+Extension.swift in Sources */,
|
||||
1DAD0FFE26AAB40000216E83 /* ActionRunJavaScriptModel.swift in Sources */,
|
||||
946EE1AB237B5C940036751F /* Decoder.swift in Sources */,
|
||||
@ -930,7 +879,6 @@
|
||||
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 */,
|
||||
D2DEDCB923C6400600C44CC4 /* UnitInterval.swift in Sources */,
|
||||
@ -940,7 +888,6 @@
|
||||
D27073B725BB45C4001C7246 /* ActionActionsModel.swift in Sources */,
|
||||
946EE1B2237B5F260036751F /* JSONValue.swift in Sources */,
|
||||
0ACC81A22613C73800A9C886 /* ActionContactModel.swift in Sources */,
|
||||
AFBB96971FBA3A9A0008D868 /* MVMCorePresentViewControllerOperation.m in Sources */,
|
||||
AF69D4EF286E612800BC6862 /* ActionOpenSMSHandler.swift in Sources */,
|
||||
AF43A5781FBA5B7C008E9347 /* MVMCoreJSONConstants.m in Sources */,
|
||||
AFBB96691FBA3A570008D868 /* MVMCoreRequestParameters.m in Sources */,
|
||||
@ -979,20 +926,17 @@
|
||||
EA09CD99282BF83600A7835F /* DecodableDefault.swift in Sources */,
|
||||
01C851D123CF97FE0021F976 /* ActionBackModel.swift in Sources */,
|
||||
D27073D125BB844B001C7246 /* ActionDelegateProtocol.swift in Sources */,
|
||||
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 */,
|
||||
AF43A5841FBB66DE008E9347 /* MVMCoreConstants.m in Sources */,
|
||||
AF69D4F1286E9D8000BC6862 /* ActionNoopHandler.swift in Sources */,
|
||||
016FF6F2259A4FCC00F5E4AA /* ClientParameterModel.swift in Sources */,
|
||||
D2DEDCBB23C65BC300C44CC4 /* Percent.swift in Sources */,
|
||||
60CBD0542A02397A00056CB0 /* MVMCoreSessionTimeHandler.swift in Sources */,
|
||||
AF686FDC2A8A87EA008F666A /* KVOPublisher.swift in Sources */,
|
||||
AFBB966A1FBA3A570008D868 /* MVMCoreLoadRequestOperation.m in Sources */,
|
||||
D268D82C26700292008BD413 /* MVMCoreViewManagerViewControllerProtocolHelper.m in Sources */,
|
||||
0AEBB84625FA75C000EA80EE /* ActionOpenSMSModel.swift in Sources */,
|
||||
|
||||
@ -21,12 +21,6 @@ open class ActionBackHandler: MVMCoreJSONActionHandlerProtocol {
|
||||
}
|
||||
|
||||
open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
|
||||
await withCheckedContinuation { continuation in
|
||||
Task(priority: .userInitiated) {
|
||||
await MVMCoreNavigationHandler.shared()?.removeCurrentViewController(true, completionHandler: {
|
||||
continuation.resume()
|
||||
})
|
||||
}
|
||||
}
|
||||
await NavigationHandler.shared().removeCurrentViewController(delegateObject: delegateObject)
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,9 @@ open class ActionContactHandler: NSObject, MVMCoreActionHandlerProtocol, CNConta
|
||||
// Setting to accessibilityValue as a workaround to pass data via the delegate function.
|
||||
controller.view.accessibilityIdentifier = model.phoneNumber
|
||||
controller.delegate = self
|
||||
MVMCoreNavigationHandler.shared()?.present(controller, animated: true)
|
||||
Task(priority: .userInitiated) {
|
||||
await NavigationHandler.shared().present(viewController: controller, delegateObject: delegateObject, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
case .create:
|
||||
@ -58,7 +60,9 @@ open class ActionContactHandler: NSObject, MVMCoreActionHandlerProtocol, CNConta
|
||||
let controller = CNContactViewController(forNewContact: contact)
|
||||
controller.contactStore = store
|
||||
controller.delegate = self
|
||||
MVMCoreNavigationHandler.shared()?.push(controller, animated: true)
|
||||
Task(priority: .userInitiated) {
|
||||
await NavigationHandler.shared().push(viewController: controller, delegateObject: delegateObject, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
case .view:
|
||||
@ -74,16 +78,19 @@ open class ActionContactHandler: NSObject, MVMCoreActionHandlerProtocol, CNConta
|
||||
let controller = CNContactViewController(forNewContact: viewContact)
|
||||
controller.contactStore = store
|
||||
controller.delegate = self
|
||||
MVMCoreNavigationHandler.shared()?.push(controller, animated: true)
|
||||
Task(priority: .userInitiated) {
|
||||
await NavigationHandler.shared().push(viewController: controller, delegateObject: delegateObject, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?) {
|
||||
MVMCoreNavigationHandler.shared()?.popTopViewController(animated: true, navigationController: nil, delegate: nil, completionHandler: {
|
||||
Task(priority: .userInitiated) {
|
||||
await NavigationHandler.shared().popTopViewController()
|
||||
self.continuation?.resume(returning: true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func contactViewController(_ viewController: CNContactViewController, shouldPerformDefaultActionFor property: CNContactProperty) -> Bool {
|
||||
@ -91,9 +98,10 @@ open class ActionContactHandler: NSObject, MVMCoreActionHandlerProtocol, CNConta
|
||||
}
|
||||
|
||||
public func contactPickerDidCancel(_ picker: CNContactPickerViewController) {
|
||||
MVMCoreNavigationHandler.shared()?.dismissTopViewController(animated: true, delegate: nil, completionHandler: {
|
||||
Task(priority: .userInitiated) {
|
||||
await NavigationHandler.shared().dismissTopViewController()
|
||||
self.continuation?.resume(returning: true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
|
||||
@ -110,7 +118,9 @@ open class ActionContactHandler: NSObject, MVMCoreActionHandlerProtocol, CNConta
|
||||
let controller = CNContactViewController(forNewContact: existingContact)
|
||||
controller.contactStore = store
|
||||
controller.delegate = self
|
||||
MVMCoreNavigationHandler.shared()?.push(controller, animated: true)
|
||||
Task(priority: .userInitiated) {
|
||||
await NavigationHandler.shared().push(viewController: controller)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,9 @@ open class ActionShareHandler: MVMCoreActionHandlerProtocol {
|
||||
continuation.resume()
|
||||
}
|
||||
}
|
||||
MVMCoreNavigationHandler.shared()?.present(controller, animated: true)
|
||||
Task(priority: .high) {
|
||||
await NavigationHandler.shared().present(viewController: controller)
|
||||
}
|
||||
} as Void
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
#import "MVMCoreLoadRequestOperation.h"
|
||||
#import "MVMCoreCache.h"
|
||||
#import "MFHardCodedServerResponse.h"
|
||||
#import "MVMCoreNavigationHandler.h"
|
||||
#import "MVMCoreLoadObject.h"
|
||||
#import "MVMCoreSessionObject.h"
|
||||
#import "MVMCoreJSONConstants.h"
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
@class MVMCoreLoadObject;
|
||||
@class DelegateObject;
|
||||
|
||||
@interface MVMCoreLoadRequestOperation : MVMCoreOperation <MVMCorePresentationDelegateProtocol>
|
||||
@interface MVMCoreLoadRequestOperation : MVMCoreOperation
|
||||
|
||||
@property (nullable, strong, nonatomic) MVMCoreRequestParameters *requestParameters;
|
||||
@property (nullable, strong, nonatomic) MVMCoreLoadObject *loadObject;
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#import "MVMCoreLoggingHandler.h"
|
||||
#import "MVMCoreSessionObject.h"
|
||||
#import "MVMCoreViewControllerMappingObject.h"
|
||||
#import "MVMCoreNavigationHandler.h"
|
||||
#import <MVMCore/MVMCoreDispatchUtility.h>
|
||||
#import "MVMCoreLoadObject.h"
|
||||
#import "MVMCoreRequestParameters.h"
|
||||
@ -483,7 +482,7 @@
|
||||
} else if ([ValuePresentationStylePopToPage isEqualToString:[loadObject.pageJSON string:KeyPresentationStyle]] && !loadObject.operation.backgroundLoad && !loadObject.requestParameters.noViewControllerToLoad) {
|
||||
|
||||
// We need to pop back to a page instead of loading a new page.
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] popToViewControllerWithPageType:[loadObject.pageJSON string:@"popBackPageType"] navigationController:loadObject.requestParameters.navigationController animated:!loadObject.requestParameters.shouldNotAnimatePush delegate:loadObject.operation completionHandler:^{
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] popToViewControllerWithPageType:[loadObject.pageJSON string:@"popBackPageType"] navigationController:loadObject.requestParameters.navigationController animated:!loadObject.requestParameters.shouldNotAnimatePush delegate:loadObject.delegateObject.presentationDelegate completionHandler:^{
|
||||
[MVMCoreLoadRequestOperation loadFinished:loadObject loadedViewController:nil errorObject:error];
|
||||
}];
|
||||
|
||||
@ -777,7 +776,7 @@
|
||||
}
|
||||
|
||||
// Once displyed, we are finished.
|
||||
[MVMCoreActionUtility displayViewController:viewController forLoadObject:loadObject presentationDelegate:loadObject.operation completionHandler:^{
|
||||
[MVMCoreActionUtility displayViewController:viewController forLoadObject:loadObject presentationDelegate:loadObject.delegateObject.presentationDelegate completionHandler:^{
|
||||
[MVMCoreLoadRequestOperation loadFinished:loadObject loadedViewController:viewController errorObject:error];
|
||||
}];
|
||||
}
|
||||
@ -892,65 +891,4 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Presentation Delegate
|
||||
- (void)navigationController:(UINavigationController *)navigationController prepareDisplayForViewController:(UIViewController *)viewController {
|
||||
if ([self.delegateObject.presentationDelegate respondsToSelector:@selector(navigationController:prepareDisplayForViewController:)]) {
|
||||
[self.delegateObject.presentationDelegate navigationController:navigationController prepareDisplayForViewController:viewController];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)navigationController:(UINavigationController *)navigationController willDisplayViewController:(UIViewController *)viewController {
|
||||
|
||||
// stop any loading animation we may have started if we are about to display
|
||||
if (!self.backgroundLoad && !self.requestParameters.noloadingOverlay) {
|
||||
[[MVMCoreLoadingOverlayHandler sharedLoadingOverlay] stopLoading:NO];
|
||||
}
|
||||
|
||||
if ([self.delegateObject.presentationDelegate respondsToSelector:@selector(navigationController:willDisplayViewController:)]) {
|
||||
[self.delegateObject.presentationDelegate navigationController:navigationController willDisplayViewController:viewController];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)navigationController:(UINavigationController *)navigationController displayedViewController:(UIViewController *)viewController {
|
||||
|
||||
if ([self.delegateObject.presentationDelegate respondsToSelector:@selector(navigationController:displayedViewController:)]) {
|
||||
[self.delegateObject.presentationDelegate navigationController:navigationController displayedViewController:viewController];
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
|
||||
if (self.delegateObject.presentationDelegate && [self.delegateObject.presentationDelegate respondsToSelector:@selector(navigationController:animationControllerForOperation:fromViewController:toViewController:)]) {
|
||||
|
||||
return [self.delegateObject.presentationDelegate navigationController:navigationController animationControllerForOperation:operation fromViewController:fromVC toViewController:toVC];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {
|
||||
if (self.delegateObject.presentationDelegate && [self.delegateObject.presentationDelegate respondsToSelector:@selector(navigationController:interactionControllerForAnimationController:)]) {
|
||||
return [self.delegateObject.presentationDelegate navigationController:navigationController interactionControllerForAnimationController:animationController];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)navigationController:(UINavigationController *)navigationController interactiveTransitionWasCanceled:(BOOL)canceled {
|
||||
if (self.delegateObject.presentationDelegate && [self.delegateObject.presentationDelegate respondsToSelector:@selector(navigationController:interactiveTransitionWasCanceled:)]) {
|
||||
[self.delegateObject.presentationDelegate navigationController:navigationController interactiveTransitionWasCanceled:canceled];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewController:(UIViewController *)presentingViewController willPresentViewController:(UIViewController *)presentedViewController {
|
||||
if ([self.delegateObject.presentationDelegate respondsToSelector:@selector(viewController:willPresentViewController:)]) {
|
||||
[self.delegateObject.presentationDelegate viewController:presentingViewController willPresentViewController:presentedViewController];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewController:(UIViewController *)presentingViewController didPresentViewController:(UIViewController *)presentedViewController {
|
||||
if ([self.delegateObject.presentationDelegate respondsToSelector:@selector(viewController:didPresentViewController:)]) {
|
||||
[self.delegateObject.presentationDelegate viewController:presentingViewController didPresentViewController:presentedViewController];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -56,12 +56,6 @@ FOUNDATION_EXPORT const unsigned char MVMCoreVersionString[];
|
||||
|
||||
// Presentation Handling
|
||||
#import <MVMCore/MVMCorePresentationDelegateProtocol.h>
|
||||
#import <MVMCore/MVMCoreNavigationHandler.h>
|
||||
#import <MVMCore/MVMCoreNavigationObject.h>
|
||||
#import <MVMCore/MVMCoreDismissViewControllerOperation.h>
|
||||
#import <MVMCore/MVMCorePresentAnimationOperation.h>
|
||||
#import <MVMCore/MVMCorePresentViewControllerOperation.h>
|
||||
#import <MVMCore/MVMCoreNavigationOperation.h>
|
||||
#import <MVMCore/MVMCoreViewControllerAnimatedTransitioning.h>
|
||||
|
||||
// Action Handling
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
//
|
||||
// MVMCoreDismissViewControllerOperation.h
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 9/28/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// Operation for dismissing an alert view controller. Needs to be added to the main queue
|
||||
|
||||
#import <MVMCore/MVMCoreOperation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface MVMCoreDismissViewControllerOperation : MVMCoreOperation
|
||||
|
||||
// Goes up the presentation chain to only dismiss the top presented.
|
||||
- (nullable instancetype)initAndDismissTopViewController:(nullable UIViewController *)viewController animated:(BOOL)animated;
|
||||
|
||||
// Dismiss the passed in view controller.
|
||||
- (nullable instancetype)initAndDismissViewController:(nullable UIViewController *)viewController animated:(BOOL)animated;
|
||||
|
||||
@end
|
||||
@ -1,91 +0,0 @@
|
||||
//
|
||||
// MVMCoreDismissViewControllerOperation.m
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 9/28/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCoreDismissViewControllerOperation.h"
|
||||
#import "MVMCoreConstants.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, DismissType) {
|
||||
DismissTypeTop = 0,
|
||||
DismissTypeSpecific
|
||||
};
|
||||
|
||||
@interface MVMCoreDismissViewControllerOperation ()
|
||||
@property (nullable, strong, nonatomic) UIViewController *viewController;
|
||||
@property (nonatomic) BOOL animate;
|
||||
@property (nonatomic) DismissType type;
|
||||
@end
|
||||
|
||||
@implementation MVMCoreDismissViewControllerOperation
|
||||
|
||||
- (nullable instancetype)initAndDismissTopViewController:(nullable UIViewController *)viewController animated:(BOOL)animated {
|
||||
|
||||
if (self = [super init]) {
|
||||
self.viewController = viewController;
|
||||
self.animate = animated;
|
||||
self.type = DismissTypeTop;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initAndDismissViewController:(nullable UIViewController *)viewController animated:(BOOL)animated {
|
||||
|
||||
if (self = [super init]) {
|
||||
self.viewController = viewController;
|
||||
self.animate = animated;
|
||||
self.type = DismissTypeSpecific;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)main {
|
||||
|
||||
// Always check for cancellation before launching the task.
|
||||
if ([self checkAndHandleForCancellation]) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (self.type) {
|
||||
case DismissTypeTop:
|
||||
{
|
||||
// Gets the top most presented.
|
||||
UIViewController *controllerToDismiss = self.viewController;
|
||||
while (controllerToDismiss.presentedViewController) {
|
||||
controllerToDismiss = controllerToDismiss.presentedViewController;
|
||||
}
|
||||
[self dismissViewController:controllerToDismiss];
|
||||
}
|
||||
break;
|
||||
case DismissTypeSpecific:
|
||||
{
|
||||
if (self.viewController.presentingViewController) {
|
||||
[self dismissViewController:self.viewController.presentingViewController];
|
||||
} else {
|
||||
[self dismissViewController:self.viewController];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dismissViewController:(nonnull UIViewController *)viewController {
|
||||
if (viewController.presentedViewController || viewController.presentingViewController) {
|
||||
[viewController dismissViewControllerAnimated:self.animate completion:^{
|
||||
[self markAsFinished];
|
||||
// Notify that page has changed
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MVMCoreNotificationViewControllerChanged object:nil];
|
||||
});
|
||||
}];
|
||||
} else {
|
||||
[self markAsFinished];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,153 +0,0 @@
|
||||
//
|
||||
// MVMCoreNavigationHandler.h
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 11/18/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// This class should be used to handle all navigation and presentation for mvm.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <MVMCore/MVMCorePresentationDelegateProtocol.h>
|
||||
|
||||
@class MVMCoreOperation;
|
||||
@class MVMCoreNavigationObject;
|
||||
@class MVMCoreLoadObject;
|
||||
|
||||
@interface MVMCoreNavigationHandler : NSObject <UINavigationControllerDelegate>
|
||||
|
||||
// Returns the shared instance of this singleton
|
||||
+ (nullable instancetype)sharedNavigationHandler;
|
||||
|
||||
// Can set the view controller to present on... will use MF if nil.
|
||||
@property (nullable, nonatomic, weak) UIViewController *viewControllerToPresentOn;
|
||||
|
||||
// reference to main navigation controller
|
||||
@property (nullable, weak, nonatomic) UINavigationController *navigationController;
|
||||
|
||||
/// A list of possible delegates looking for information.
|
||||
@property (nonnull, strong, nonatomic) NSHashTable<MVMCorePresentationDelegateProtocol> *delegates;
|
||||
|
||||
// Will navigate appropriately based on the load style
|
||||
- (void)navigateWithLoadObject:(nullable MVMCoreLoadObject *)loadObject viewController:(nonnull UIViewController *)viewController delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Perform navigation with object.
|
||||
- (void)startNavigationWithNavigationObject:(nonnull MVMCoreNavigationObject *)navigationObject delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// pops or dimisses as needed
|
||||
- (void)removeCurrentViewController;
|
||||
|
||||
/// Dismisses or pops the current view controller.
|
||||
- (void)removeCurrentViewController:(BOOL)animated completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
#pragma mark - Delegate Handling
|
||||
|
||||
/// Adds a listener for navigation delegate functions
|
||||
- (void)addDelegate:(nonnull id <MVMCorePresentationDelegateProtocol>)delegate;
|
||||
|
||||
/// Removes a listener for navigation delegate functions
|
||||
- (void)removeDelegate:(nullable id <MVMCorePresentationDelegateProtocol>)delegate;
|
||||
|
||||
#pragma mark - Navigation Simple
|
||||
// Uses the default navigation controller in app delegate
|
||||
|
||||
// Use this to push.
|
||||
- (void)pushViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated;
|
||||
|
||||
// Use this to replace the top view controller.
|
||||
- (void)replaceTopViewControllerWithViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated;
|
||||
|
||||
// Use this to replace all the view controllers after the root with the passed in view controller.
|
||||
- (void)replaceAfterRoot:(nonnull UIViewController *)viewController animated:(BOOL)animated;
|
||||
|
||||
// Use this to set the navigation stack.
|
||||
- (void)setViewControllers:(nonnull NSArray *)viewControllers animated:(BOOL)animated;
|
||||
|
||||
// Use this to pop.
|
||||
- (void)popTopViewControllerAnimated:(BOOL)animated;
|
||||
|
||||
// Use this to pop a specific view controller.
|
||||
- (void)popViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated;
|
||||
|
||||
// Use this to pop to a specific view controller in the stack.
|
||||
- (void)popToViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated;
|
||||
|
||||
// Use this to pop to a view controller of a specific class in the stack.
|
||||
- (void)popToInstanceOfClass:(nonnull Class)viewControllerClass animated:(BOOL)animated;
|
||||
|
||||
// Use this to pop to a view controller of a specific page type in the stack.
|
||||
- (void)popToViewControllerWithPageType:(nonnull NSString *)pageType animated:(BOOL)animated;
|
||||
|
||||
// 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;
|
||||
|
||||
#pragma mark - Navigation Extra
|
||||
|
||||
// Use this to push.
|
||||
- (void)pushViewController:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate replaceInStack:(BOOL)replaceInStack completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to replace the top view controller.
|
||||
- (void)replaceTopViewControllerWithViewController:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate replaceInStack:(BOOL)replaceInStack completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to replace all the view controllers after the root with the passed in view controller. If no navigation controller is provided, will use the main one in app delegate.
|
||||
- (void)replaceAfterRoot:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate replaceInStack:(BOOL)replaceInStack completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to set the navigation stack. If no navigation controller is provided, will use the main one in app delegate.
|
||||
- (void)setViewControllers:(nonnull NSArray *)viewControllers navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate replaceInStack:(BOOL)replaceInStack completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to pop. If no navigation controller is provided, will use the main one in app delegate.
|
||||
- (void)popTopViewControllerAnimated:(BOOL)animated navigationController:(nullable UINavigationController *)navigationController delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to pop a specific view controller. If no navigation controller is provided, will use the main one in app delegate.
|
||||
- (void)popViewController:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to pop to a specific view controller in the stack. If no navigation controller is provided, will use the main one in app delegate.
|
||||
- (void)popToViewController:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to pop to a view controller of a specific class in the stack. If no navigation controller is provided, will use the main one in app delegate.
|
||||
- (void)popToInstanceOfClass:(nonnull Class)viewControllerClass navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to pop to a view controller of a specific pageType in the stack. If no navigation controller is provided, will use the main one in app delegate.
|
||||
- (void)popToViewControllerWithPageType:(nonnull NSString *)pageType navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to pop to the root of the stack. If no navigation controller is provided, will use the main one in app delegate.
|
||||
- (void)popToRootAnimated:(BOOL)animated navigationController:(nullable UINavigationController *)navigationController delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
/// Returns the view controllers of the navigation controller. Takes into account navigation controller animation states.
|
||||
- (nullable NSArray<UIViewController *> *)getViewControllersForNavigationController:(nullable UINavigationController *)navigationController;
|
||||
|
||||
#pragma mark - Presentation Simple
|
||||
|
||||
// Use this to present.
|
||||
- (void)presentViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated;
|
||||
|
||||
// Use this to dismiss.
|
||||
- (void)dismissTopViewControllerAnimated:(BOOL)animated;
|
||||
|
||||
// Use this to dismiss a specific view controller and any it may be presenting.
|
||||
- (void)dismissViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated;
|
||||
|
||||
// Use this to dismiss all presented view controllers stacked on the bottom one.
|
||||
- (void)dismissToBottom:(BOOL)animated;
|
||||
|
||||
#pragma mark - Presentation Extra
|
||||
|
||||
// Use this to present.
|
||||
- (void)presentViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to dismiss.
|
||||
- (void)dismissTopViewControllerAnimated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to dismiss a specific view controller and any it may be presenting.
|
||||
- (void)dismissViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
// Use this to dismiss all presented view controllers stacked on the bottom one.
|
||||
- (void)dismissToBottom:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
|
||||
|
||||
@end
|
||||
@ -1,353 +0,0 @@
|
||||
//
|
||||
// MVMCoreNavigationHandler.m
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 11/18/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCoreNavigationHandler.h"
|
||||
#import "MVMCoreNavigationOperation.h"
|
||||
#import "MVMCorePresentViewControllerOperation.h"
|
||||
#import "MVMCoreDismissViewControllerOperation.h"
|
||||
#import "MVMCoreNavigationObject.h"
|
||||
#import "MVMCoreLoadObject.h"
|
||||
#import "MVMCoreObject.h"
|
||||
#import "MVMCoreRequestParameters.h"
|
||||
#import "MVMCoreErrorConstants.h"
|
||||
#import "MVMCoreLoggingHandler.h"
|
||||
#import "MVMCoreLoadingOverlayHandler.h"
|
||||
#import "MVMCoreDispatchUtility.h"
|
||||
#import <MVMCore/MVMCore-Swift.h>
|
||||
|
||||
@interface MVMCoreNavigationHandler ()
|
||||
|
||||
@property (strong, nonatomic) NSOperationQueue *navigationQueue;
|
||||
@property (strong, nonatomic) NSOperationQueue *presentationQueue;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MVMCoreNavigationHandler
|
||||
|
||||
+ (nullable instancetype)sharedNavigationHandler {
|
||||
|
||||
static dispatch_once_t once;
|
||||
static id sharedInstance;
|
||||
|
||||
dispatch_once(&once, ^{
|
||||
sharedInstance = [[self alloc] init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
self.navigationQueue = [[NSOperationQueue alloc] init];
|
||||
self.navigationQueue.maxConcurrentOperationCount = 1;
|
||||
|
||||
self.delegates = (NSHashTable <MVMCorePresentationDelegateProtocol>*)[NSHashTable weakObjectsHashTable];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Delegate Handling
|
||||
|
||||
- (void)addDelegate:(nonnull id <MVMCorePresentationDelegateProtocol>)delegate {
|
||||
[self.delegates addObject:delegate];
|
||||
}
|
||||
|
||||
- (void)removeDelegate:(nullable id <MVMCorePresentationDelegateProtocol>)delegate {
|
||||
[self.delegates removeObject:delegate];
|
||||
}
|
||||
|
||||
#pragma mark - Navigation Helpers
|
||||
|
||||
- (void)navigateWithLoadObject:(nullable MVMCoreLoadObject *)loadObject viewController:(nonnull UIViewController *)viewController delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
BOOL shouldAnimate = !loadObject.requestParameters.shouldNotAnimatePush;
|
||||
switch (loadObject.requestParameters.loadStyle) {
|
||||
|
||||
case MFLoadStyleReplaceCurrent:
|
||||
{
|
||||
// Replace current screen.
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] replaceTopViewControllerWithViewController:viewController navigationController:loadObject.requestParameters.navigationController animated:shouldAnimate delegate:delegate replaceInStack:loadObject.requestParameters.replaceViewIfOnStackElseLoadWithStyle completionHandler:completionBlock];
|
||||
}
|
||||
break;
|
||||
case MFLoadStyleOnTopOfRoot:
|
||||
{
|
||||
// Pushes ater the root.
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] replaceAfterRoot:viewController navigationController:loadObject.requestParameters.navigationController animated:shouldAnimate delegate:delegate replaceInStack:loadObject.requestParameters.replaceViewIfOnStackElseLoadWithStyle completionHandler:completionBlock];
|
||||
}
|
||||
break;
|
||||
case MFLoadStyleBecomeRoot:
|
||||
{
|
||||
// Loads as root the root.
|
||||
NSArray *replaceViewControllers = @[viewController];
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] setViewControllers:replaceViewControllers navigationController:loadObject.requestParameters.navigationController animated:shouldAnimate delegate:delegate replaceInStack:loadObject.requestParameters.replaceViewIfOnStackElseLoadWithStyle completionHandler:completionBlock];
|
||||
}
|
||||
break;
|
||||
case MFLoadStylePresent:
|
||||
{
|
||||
// Present as modal.
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] presentViewController:viewController animated:shouldAnimate delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// Just pushes.
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] pushViewController:viewController navigationController:loadObject.requestParameters.navigationController animated:shouldAnimate delegate:delegate replaceInStack:loadObject.requestParameters.replaceViewIfOnStackElseLoadWithStyle completionHandler:completionBlock];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startNavigationWithNavigationObject:(MVMCoreNavigationObject *)navigationObject delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)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;
|
||||
[self.navigationQueue addOperation:navigationOperation];
|
||||
}
|
||||
|
||||
- (void)removeCurrentViewController {
|
||||
[self removeCurrentViewController:YES completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)removeCurrentViewController:(BOOL)animated completionHandler:(nullable void (^)(void))completionBlock {
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
// presentedViewController must be used on main thread
|
||||
if (self.viewControllerToPresentOn.presentedViewController) {
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] dismissTopViewControllerAnimated:animated delegate:nil completionHandler:completionBlock];
|
||||
} else {
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] popTopViewControllerAnimated:animated navigationController:nil delegate:nil completionHandler:completionBlock];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Navigation Simple
|
||||
|
||||
- (void)pushViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:nil viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePush];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)replaceTopViewControllerWithViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:nil viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypeReplaceTop];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)replaceAfterRoot:(nonnull UIViewController *)viewController animated:(BOOL)animated {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:nil viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypeReplaceAfterRoot];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)setViewControllers:(nonnull NSArray *)viewControllers animated:(BOOL)animated {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:nil viewControllers:viewControllers animated:animated tryToReplaceFirst:NO navigationType:NavigationTypeSet];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)popTopViewControllerAnimated:(BOOL)animated {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:nil viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePop];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)popViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:nil viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopSpecific];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)popToViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:nil viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopTo];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)popToInstanceOfClass:(nonnull Class)viewControllerClass animated:(BOOL)animated {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:nil viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopTo];
|
||||
navigationObject.classToPopTo = viewControllerClass;
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)popToViewControllerWithPageType:(nonnull NSString *)pageType animated:(BOOL)animated {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:nil viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopTo];
|
||||
navigationObject.pageTypeToPopTo = pageType;
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (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];
|
||||
}
|
||||
|
||||
- (void)addNavigationOperation:(nonnull MVMCoreOperation *)operation {
|
||||
[self.navigationQueue addOperation:operation];
|
||||
}
|
||||
|
||||
- (void)cancelNavigation {
|
||||
[self.navigationQueue cancelAllOperations];
|
||||
}
|
||||
|
||||
#pragma mark - Navigation Extra
|
||||
|
||||
- (void)pushViewController:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate replaceInStack:(BOOL)replaceInStack completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:navigationController viewControllers:nil animated:animated tryToReplaceFirst:replaceInStack navigationType:NavigationTypePush];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (void)replaceTopViewControllerWithViewController:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate replaceInStack:(BOOL)replaceInStack completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:navigationController viewControllers:nil animated:animated tryToReplaceFirst:replaceInStack navigationType:NavigationTypeReplaceTop];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (void)replaceAfterRoot:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate replaceInStack:(BOOL)replaceInStack completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:navigationController viewControllers:nil animated:animated tryToReplaceFirst:replaceInStack navigationType:NavigationTypeReplaceAfterRoot];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (void)setViewControllers:(nonnull NSArray *)viewControllers navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate replaceInStack:(BOOL)replaceInStack completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:navigationController viewControllers:viewControllers animated:animated tryToReplaceFirst:replaceInStack navigationType:NavigationTypeSet];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (void)popTopViewControllerAnimated:(BOOL)animated navigationController:(nullable UINavigationController *)navigationController delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:navigationController viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePop];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (void)popViewController:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:navigationController viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopSpecific];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (void)popToViewController:(nonnull UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:viewController navigationController:navigationController viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopTo];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (void)popToInstanceOfClass:(nonnull Class)viewControllerClass navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:navigationController viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopTo];
|
||||
navigationObject.classToPopTo = viewControllerClass;
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (void)popToViewControllerWithPageType:(nonnull NSString *)pageType navigationController:(nullable UINavigationController *)navigationController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:navigationController viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopTo];
|
||||
navigationObject.pageTypeToPopTo = pageType;
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (void)popToRootAnimated:(BOOL)animated navigationController:(nullable UINavigationController *)navigationController delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreNavigationObject *navigationObject = [[MVMCoreNavigationObject alloc] initWithViewController:nil navigationController:navigationController viewControllers:nil animated:animated tryToReplaceFirst:NO navigationType:NavigationTypePopToRoot];
|
||||
[self startNavigationWithNavigationObject:navigationObject delegate:delegate completionHandler:completionBlock];
|
||||
}
|
||||
|
||||
- (nullable NSArray<UIViewController *> *)getViewControllersForNavigationController:(nullable UINavigationController *)navigationController {
|
||||
// Check if we are currently animating.
|
||||
NSInteger index = [self.navigationQueue.operations indexOfObjectPassingTest:^BOOL(__kindof MVMCoreNavigationOperation * _Nonnull operation, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
return operation.isExecuting && [operation isKindOfClass:[MVMCoreNavigationOperation class]];
|
||||
}];
|
||||
|
||||
if (index != NSNotFound) {
|
||||
// Test above ensures we have an MVMCoreNavigationOperation. There are situations where block operations are submitted to the queue to be executed.
|
||||
MVMCoreNavigationOperation *operation = [self.navigationQueue.operations objectAtIndex:index];
|
||||
if (operation.navigationObject.navigationController == navigationController && operation.futureViewControllers) {
|
||||
// Return the future state if animating.
|
||||
return operation.futureViewControllers;
|
||||
}
|
||||
}
|
||||
return navigationController.viewControllers;
|
||||
}
|
||||
|
||||
#pragma mark - Presentation Simple
|
||||
|
||||
- (void)presentViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated {
|
||||
|
||||
[self presentViewController:viewController animated:animated delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
|
||||
- (void)dismissTopViewControllerAnimated:(BOOL)animated {
|
||||
|
||||
[self dismissTopViewControllerAnimated:animated delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)dismissViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated {
|
||||
|
||||
[self dismissViewController:viewController animated:animated delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
- (void)dismissToBottom:(BOOL)animated {
|
||||
|
||||
[self dismissToBottom:animated delegate:nil completionHandler:NULL];
|
||||
}
|
||||
|
||||
#pragma mark - Presentation Extra
|
||||
|
||||
- (void)presentViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
UIViewController *controllerToPresentOn = self.viewControllerToPresentOn ?: [MVMCoreGetterUtility getKeyWindow].rootViewController;
|
||||
if (!controllerToPresentOn) {
|
||||
// Log if we are attempting to add an alert to nothing.
|
||||
MVMCoreErrorObject *error = [[MVMCoreErrorObject alloc] initWithTitle:nil message:@"The viewControllerToPresent on property is nil and an attempt was made to present." code:ErrorCodeNoViewControllerToPresentOn domain:ErrorDomainNative location:[NSString stringWithFormat:@"ViewController:%@|Delegate:%@",viewController.description,delegate]];
|
||||
[MVMCoreLoggingHandler addErrorToLog:error];
|
||||
} else {
|
||||
MVMCorePresentViewControllerOperation *operation = [[MVMCorePresentViewControllerOperation alloc] initWithPresentingViewController:controllerToPresentOn presentedViewController:viewController animated:animated];
|
||||
operation.delegate = delegate;
|
||||
operation.completionBlock = completionBlock;
|
||||
[self.navigationQueue addOperation:operation];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)dismissTopViewControllerAnimated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
// Dismiss on the main navigation controller.
|
||||
UIViewController *controllerToPresentOn = self.viewControllerToPresentOn ?: [MVMCoreGetterUtility getKeyWindow].rootViewController;
|
||||
MVMCoreDismissViewControllerOperation *operation = [[MVMCoreDismissViewControllerOperation alloc] initAndDismissTopViewController:controllerToPresentOn animated:animated];
|
||||
operation.completionBlock = completionBlock;
|
||||
[[NSOperationQueue mainQueue] addOperation:operation];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)dismissViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
|
||||
MVMCoreDismissViewControllerOperation *operation = [[MVMCoreDismissViewControllerOperation alloc] initAndDismissViewController:viewController animated:animated];
|
||||
operation.completionBlock = completionBlock;
|
||||
[[NSOperationQueue mainQueue] addOperation:operation];
|
||||
}
|
||||
|
||||
- (void)dismissToBottom:(BOOL)animated delegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
// Dismiss on the main navigation controller.
|
||||
UIViewController *controllerToPresentOn = self.viewControllerToPresentOn ?: [MVMCoreGetterUtility getKeyWindow].rootViewController;
|
||||
MVMCoreDismissViewControllerOperation *operation = [[MVMCoreDismissViewControllerOperation alloc] initAndDismissViewController:controllerToPresentOn animated:animated];
|
||||
operation.completionBlock = completionBlock;
|
||||
[[NSOperationQueue mainQueue] addOperation:operation];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,103 +0,0 @@
|
||||
//
|
||||
// MVMCoreNavigationHandler.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Scott Pfeil on 8/29/22.
|
||||
// Copyright © 2022 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
@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<MVMCorePresentationDelegateProtocol> = NSHashTable.weakObjects()
|
||||
|
||||
// MARK: - Publishers
|
||||
|
||||
/// Publishes when the navigation will begin
|
||||
public let onNavigationWillBegin = PassthroughSubject<(NavigationType, [UIViewController]), Never>()
|
||||
|
||||
/// Publishes when a viewcontroller did show.
|
||||
public let onNavigationDidFinish = PassthroughSubject<(NavigationType), Never>()
|
||||
|
||||
// MARK: -
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
//
|
||||
// MVMCoreNavigationObject.h
|
||||
// mobilefirst
|
||||
//
|
||||
// Created by Scott Pfeil on 4/22/16.
|
||||
// Copyright © 2016 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <MVMCore/MVMCoreConstants.h>
|
||||
|
||||
@interface MVMCoreNavigationObject : NSObject
|
||||
|
||||
@property (nullable, strong, nonatomic) UIViewController *viewController;
|
||||
@property (nullable, strong, nonatomic) UINavigationController *navigationController;
|
||||
@property (nullable, strong, nonatomic) NSArray *viewControllers;
|
||||
@property (nullable, strong, nonatomic) Class classToPopTo;
|
||||
@property (nullable, strong, nonatomic) NSString *pageTypeToPopTo;
|
||||
@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;
|
||||
|
||||
@end
|
||||
@ -1,31 +0,0 @@
|
||||
//
|
||||
// MVMCoreNavigationObject.m
|
||||
// mobilefirst
|
||||
//
|
||||
// Created by Scott Pfeil on 4/22/16.
|
||||
// Copyright © 2016 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCoreNavigationObject.h"
|
||||
#import "MVMCoreNavigationHandler.h"
|
||||
|
||||
@implementation MVMCoreNavigationObject
|
||||
|
||||
- (nullable instancetype)initWithViewController:(nullable UIViewController *)viewController navigationController:(nullable UINavigationController *)navigationController viewControllers:(nullable NSArray *)viewControllers animated:(BOOL)animated tryToReplaceFirst:(BOOL)tryToReplaceFirst navigationType:(NavigationType)navigationType {
|
||||
if (self = [super init]) {
|
||||
|
||||
self.viewController = viewController;
|
||||
|
||||
UINavigationController *navigationToUse = navigationController ?: [MVMCoreNavigationHandler sharedNavigationHandler].navigationController;
|
||||
self.navigationController = navigationToUse;
|
||||
|
||||
self.viewControllers = viewControllers;
|
||||
self.animated = animated;
|
||||
self.tryToReplaceFirst = tryToReplaceFirst;
|
||||
self.navigationType = navigationType;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@ -1,26 +0,0 @@
|
||||
//
|
||||
// MVMCoreNavigationOperation.h
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 11/17/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// Handles navigation
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <MVMCore/MVMCoreOperation.h>
|
||||
#import <MVMCore/MVMCorePresentationDelegateProtocol.h>
|
||||
|
||||
@class MVMCoreNavigationObject;
|
||||
|
||||
@interface MVMCoreNavigationOperation : MVMCoreOperation <UINavigationControllerDelegate>
|
||||
|
||||
@property (nonnull, strong, nonatomic) MVMCoreNavigationObject *navigationObject;
|
||||
@property (nullable, weak, nonatomic) NSObject<MVMCorePresentationDelegateProtocol> *delegate;
|
||||
|
||||
/// Used to keep track of future view controller state because .viewControllers is not reliable during animation.
|
||||
@property (nullable, strong, nonatomic) NSArray <UIViewController *>*futureViewControllers;
|
||||
|
||||
- (nullable instancetype)initWithNavigationObject:(nonnull MVMCoreNavigationObject *)navigationObject;
|
||||
|
||||
@end
|
||||
@ -1,334 +0,0 @@
|
||||
//
|
||||
// MVMCoreNavigationOperation.m
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 11/17/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCoreNavigationOperation.h"
|
||||
#import "MVMCoreNavigationObject.h"
|
||||
#import "MVMCoreViewManagerProtocol.h"
|
||||
#import "MVMCoreViewControllerProtocol.h"
|
||||
#import "MVMCoreLoggingHandler.h"
|
||||
#import "MVMCoreLoadingOverlayHandler.h"
|
||||
#import "MVMCoreViewControllerAnimatedTransitioning.h"
|
||||
#import "MVMCoreNavigationHandler.h"
|
||||
|
||||
@interface MVMCoreNavigationOperation ()
|
||||
|
||||
@property (strong, nonatomic) id animatedTransitioning;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MVMCoreNavigationOperation
|
||||
|
||||
- (nullable instancetype)initWithNavigationObject:(nonnull MVMCoreNavigationObject *)navigationObject {
|
||||
if (self = [super init]) {
|
||||
self.navigationObject = navigationObject;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)main {
|
||||
|
||||
if ([self checkAndHandleForCancellation]) {
|
||||
return;
|
||||
}
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperation:[NSBlockOperation blockOperationWithBlock:^{
|
||||
self.navigationObject.navigationController.delegate = self;
|
||||
|
||||
// First, we will try to replace the view controller in the stack with any of the same.
|
||||
NSInteger location = NSNotFound;
|
||||
|
||||
if (self.navigationObject.tryToReplaceFirst) {
|
||||
|
||||
if (self.navigationObject.navigationController.viewControllers.count > 0) {
|
||||
|
||||
for (NSInteger i = self.navigationObject.navigationController.viewControllers.count - 1; i >= 0; i--) {
|
||||
|
||||
UIViewController *controller = [self.navigationObject.navigationController.viewControllers objectAtIndex:i];
|
||||
if ([self.navigationObject.viewController respondsToSelector:@selector(pageType)]) {
|
||||
|
||||
// Check if tab control.
|
||||
NSString *pageType = [self.navigationObject.viewController performSelector:@selector(pageType)];
|
||||
if ([controller conformsToProtocol:@protocol(MVMCoreViewManagerProtocol)] && [self.navigationObject.viewController conformsToProtocol:@protocol(MVMCoreViewManagerProtocol)]) {
|
||||
|
||||
// Check if page is in view manager, if so, replace it.
|
||||
if ([((UIViewController <MVMCoreViewManagerProtocol>*)controller) containsPageWithPageType:pageType]) {
|
||||
location = i;
|
||||
break;
|
||||
}
|
||||
} else if ([controller respondsToSelector:@selector(pageType)]) {
|
||||
|
||||
// Compare page type if possible.
|
||||
if ([[controller performSelector:@selector(pageType)] isEqualToString:pageType]) {
|
||||
location = i;
|
||||
break;
|
||||
}
|
||||
} else if (controller.class == self.navigationObject.viewController.class) {
|
||||
|
||||
// Fallback to class compare if page type compare is unavailable.
|
||||
location = i;
|
||||
break;
|
||||
}
|
||||
} else if (controller.class == self.navigationObject.viewController.class) {
|
||||
|
||||
// Fallback to class compare if page type compare is unavailable.
|
||||
location = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (location != NSNotFound) {
|
||||
// Replace the view controller.
|
||||
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:[self.navigationObject.navigationController.viewControllers subarrayWithRange:NSMakeRange(0, location)]];
|
||||
[viewControllers addObject:self.navigationObject.viewController];
|
||||
[self setViewControllers:viewControllers];
|
||||
} else {
|
||||
|
||||
// Load normal
|
||||
switch (self.navigationObject.navigationType) {
|
||||
case NavigationTypePush:
|
||||
{
|
||||
[self pushViewController];
|
||||
}
|
||||
break;
|
||||
case NavigationTypeSet:
|
||||
{
|
||||
[self setViewControllers:self.navigationObject.viewControllers];
|
||||
}
|
||||
break;
|
||||
case NavigationTypeReplaceTop:
|
||||
{
|
||||
if (self.navigationObject.navigationController.viewControllers.count > 0) {
|
||||
|
||||
// Replaces the current view controller.
|
||||
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:self.navigationObject.navigationController.viewControllers];
|
||||
[viewControllers replaceObjectAtIndex:([self.navigationObject.navigationController.viewControllers count] - 1) withObject:self.navigationObject.viewController];
|
||||
[self setViewControllers:viewControllers];
|
||||
} else {
|
||||
|
||||
// Just push
|
||||
[self pushViewController];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NavigationTypeReplaceAfterRoot:
|
||||
{
|
||||
if (self.navigationObject.navigationController.viewControllers.count > 0) {
|
||||
|
||||
// Replaces all after the root.
|
||||
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:self.navigationObject.navigationController.viewControllers];
|
||||
NSArray *replaceViewControllers = @[viewControllers.firstObject,self.navigationObject.viewController];
|
||||
[self setViewControllers:replaceViewControllers];
|
||||
} else {
|
||||
|
||||
// Just push
|
||||
[self pushViewController];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NavigationTypePop:
|
||||
{
|
||||
if (self.navigationObject.navigationController.viewControllers.count > 1) {
|
||||
// Although the post animation state is currently fine with pop, store anyway as a precaution
|
||||
self.futureViewControllers = [self.navigationObject.navigationController.viewControllers subarrayWithRange:NSMakeRange(0, self.navigationObject.navigationController.viewControllers.count - 1)];
|
||||
[self prepareDisplay];
|
||||
[self.navigationObject.navigationController popViewControllerAnimated:self.navigationObject.animated];
|
||||
} else {
|
||||
[self markAsFinished];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NavigationTypePopSpecific:
|
||||
{
|
||||
NSInteger location = NSNotFound;
|
||||
if (self.navigationObject.navigationController.viewControllers.count > 1) {
|
||||
for (NSInteger i = self.navigationObject.navigationController.viewControllers.count - 1; i >= 0; i--) {
|
||||
UIViewController *controller = [self.navigationObject.navigationController.viewControllers objectAtIndex:i];
|
||||
if (controller == self.navigationObject.viewController) {
|
||||
location = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (location != NSNotFound) {
|
||||
NSArray *viewControllers = [self.navigationObject.navigationController.viewControllers subarrayWithRange:NSMakeRange(0, location)];
|
||||
[self setViewControllers:viewControllers];
|
||||
} else if (self.navigationObject.viewControllers) {
|
||||
// Controller not found and specific controller set present, replace controller set instead.
|
||||
[self setViewControllers:self.navigationObject.viewControllers];
|
||||
} else {
|
||||
[self markAsFinished];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NavigationTypePopTo:
|
||||
{
|
||||
if (self.navigationObject.classToPopTo || self.navigationObject.pageTypeToPopTo) {
|
||||
for (UIViewController *controller in [self.navigationObject.navigationController viewControllers]) {
|
||||
|
||||
// If the page type to pop to or class to pop to matches...
|
||||
if ((self.navigationObject.pageTypeToPopTo && [controller respondsToSelector:@selector(pageType)] && [[controller performSelector:@selector(pageType)] isEqualToString:self.navigationObject.pageTypeToPopTo]) || (self.navigationObject.classToPopTo && [controller isKindOfClass:self.navigationObject.classToPopTo])) {
|
||||
self.navigationObject.viewController = controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.navigationObject.viewController && (self.navigationObject.viewController != self.navigationObject.navigationController.topViewController)) {
|
||||
// Store post animation state.
|
||||
NSInteger index = [[self.navigationObject.navigationController viewControllers] indexOfObject:self.navigationObject.viewController];
|
||||
self.futureViewControllers = [self.navigationObject.navigationController.viewControllers subarrayWithRange:NSMakeRange(0, index + 1)];
|
||||
[self prepareDisplay];
|
||||
[self.navigationObject.navigationController popToViewController:self.navigationObject.viewController animated:self.navigationObject.animated];
|
||||
} else {
|
||||
[self markAsFinished];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NavigationTypePopToRoot:
|
||||
{
|
||||
if (self.navigationObject.navigationController.viewControllers.count > 1) {
|
||||
// Store post animation state.
|
||||
self.futureViewControllers = @[self.navigationObject.navigationController.viewControllers.firstObject];
|
||||
[self prepareDisplay];
|
||||
[self.navigationObject.navigationController popToRootViewControllerAnimated:self.navigationObject.animated];
|
||||
} else {
|
||||
[self markAsFinished];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
[self markAsFinished];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}]];
|
||||
}
|
||||
|
||||
- (void)pushViewController {
|
||||
// Although the post animation state is currently fine with push, store anyway as a precaution
|
||||
self.futureViewControllers = [self.navigationObject.navigationController.viewControllers arrayByAddingObject:self.navigationObject.viewController];
|
||||
[self prepareDisplay];
|
||||
[self.navigationObject.navigationController pushViewController:self.navigationObject.viewController animated:self.navigationObject.animated];
|
||||
}
|
||||
|
||||
- (void)setViewControllers:(NSArray *)viewControllers {
|
||||
if (![self.navigationObject.navigationController.viewControllers isEqualToArray:viewControllers]) {
|
||||
self.futureViewControllers = viewControllers;
|
||||
[self prepareDisplay];
|
||||
[self.navigationObject.navigationController setViewControllers:viewControllers animated:self.navigationObject.animated];
|
||||
} else {
|
||||
|
||||
// If the arrays contain the same objects, then the delegate methods are never called. This is a workaround for that.
|
||||
[self markAsFinished];
|
||||
}
|
||||
}
|
||||
|
||||
// Notify delegates to prepare for the controller to be added to the navigation controller.
|
||||
- (void)prepareDisplay {
|
||||
UINavigationController *navigationController = self.navigationObject.navigationController;
|
||||
UIViewController *viewController = self.futureViewControllers.lastObject;
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(navigationController:prepareDisplayForViewController:)]) {
|
||||
[self.delegate navigationController:navigationController
|
||||
prepareDisplayForViewController:viewController];
|
||||
}
|
||||
|
||||
for (NSObject<MVMCorePresentationDelegateProtocol> *delegate in [MVMCoreNavigationHandler sharedNavigationHandler].delegates.allObjects) {
|
||||
if (delegate && [delegate respondsToSelector:@selector(navigationController:prepareDisplayForViewController:)]) {
|
||||
[delegate navigationController:navigationController
|
||||
prepareDisplayForViewController:viewController];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)markAsFinished {
|
||||
self.navigationObject.navigationController.delegate = nil;
|
||||
if (self.navigationObject.stopLoadingOverlay) {
|
||||
[[MVMCoreLoadingOverlayHandler sharedLoadingOverlay] stopLoading:YES];
|
||||
self.navigationObject.stopLoadingOverlay = NO;
|
||||
}
|
||||
if (self.animatedTransitioning) {
|
||||
[self.animatedTransitioning removeObserver:self forKeyPath:@"interactiveTransitionCanceled"];
|
||||
self.animatedTransitioning = nil;
|
||||
}
|
||||
[super markAsFinished];
|
||||
}
|
||||
|
||||
#pragma mark - Delegate
|
||||
- (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:)]) {
|
||||
[self.delegate navigationController:navigationController willDisplayViewController:viewController];
|
||||
}
|
||||
for (NSObject<MVMCorePresentationDelegateProtocol> *delegate in [MVMCoreNavigationHandler sharedNavigationHandler].delegates.allObjects) {
|
||||
if (delegate && [delegate respondsToSelector:@selector(navigationController:willDisplayViewController:)]) {
|
||||
[delegate navigationController:navigationController willDisplayViewController:viewController];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
|
||||
MVMCoreLog(@"finished %@",[viewController class]);
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(navigationController:displayedViewController:)]) {
|
||||
[self.delegate navigationController:navigationController displayedViewController:viewController];
|
||||
}
|
||||
for (NSObject<MVMCorePresentationDelegateProtocol> *delegate in [MVMCoreNavigationHandler sharedNavigationHandler].delegates.allObjects) {
|
||||
if (delegate && [delegate respondsToSelector:@selector(navigationController:displayedViewController:)]) {
|
||||
[delegate navigationController:navigationController displayedViewController:viewController];
|
||||
}
|
||||
}
|
||||
[self markAsFinished];
|
||||
// Legacy notify that page has changed
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MVMCoreNotificationViewControllerChanged object:nil];
|
||||
});
|
||||
}
|
||||
|
||||
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(navigationController:animationControllerForOperation:fromViewController:toViewController:)]) {
|
||||
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];
|
||||
self.animatedTransitioning = animatedTransitioning;
|
||||
}
|
||||
return animatedTransitioning;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)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<NSKeyValueChangeKey,id> *)change context:(void *)context {
|
||||
if ([keyPath isEqualToString:@"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
|
||||
@ -1,19 +0,0 @@
|
||||
//
|
||||
// MVMCorePresentAnimationOperation.h
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 11/25/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// Should be added to the main queue. Presents the view controller on the presenting view controller.
|
||||
|
||||
#import <MVMCore/MVMCoreOperation.h>
|
||||
#import <MVMCore/MVMCorePresentationDelegateProtocol.h>
|
||||
|
||||
@interface MVMCorePresentAnimationOperation : MVMCoreOperation
|
||||
|
||||
@property (nullable, weak, nonatomic) NSObject<MVMCorePresentationDelegateProtocol> *delegate;
|
||||
|
||||
- (nullable instancetype)initWithPresentingViewController:(nullable UIViewController *)presentingViewController presentedViewController:(nullable UIViewController *)presentedViewController animated:(BOOL)animated;
|
||||
|
||||
@end
|
||||
@ -1,63 +0,0 @@
|
||||
//
|
||||
// MVMCorePresentAnimationOperation.m
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 11/25/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCorePresentAnimationOperation.h"
|
||||
#import "MVMCoreNavigationHandler.h"
|
||||
|
||||
@interface MVMCorePresentAnimationOperation ()
|
||||
|
||||
@property (nullable, strong, nonatomic) UIViewController *presentingViewController;
|
||||
@property (nullable, strong, nonatomic) UIViewController *presentedViewController;
|
||||
@property (nonatomic) BOOL animate;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MVMCorePresentAnimationOperation
|
||||
|
||||
- (nullable instancetype)initWithPresentingViewController:(nullable UIViewController *)presentingViewController presentedViewController:(nullable UIViewController *)presentedViewController animated:(BOOL)animated {
|
||||
|
||||
if (self = [super init]) {
|
||||
self.presentedViewController = presentedViewController;
|
||||
self.presentingViewController = presentingViewController;
|
||||
self.presentedViewController.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
self.animate = animated;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)main {
|
||||
|
||||
// Always check for cancellation before launching the task.
|
||||
if ([self checkAndHandleForCancellation]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(viewController:willPresentViewController:)]) {
|
||||
[self.delegate viewController:self.presentingViewController willPresentViewController:self.presentedViewController];
|
||||
}
|
||||
for (NSObject<MVMCorePresentationDelegateProtocol> *delegate in [MVMCoreNavigationHandler sharedNavigationHandler].delegates.allObjects) {
|
||||
if (delegate && [delegate respondsToSelector:@selector(viewController:willPresentViewController:)]) {
|
||||
[delegate viewController:self.presentingViewController willPresentViewController:self.presentedViewController];
|
||||
}
|
||||
}
|
||||
|
||||
[self.presentingViewController presentViewController:self.presentedViewController animated:self.animate completion:^{
|
||||
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(viewController:didPresentViewController:)]) {
|
||||
[self.delegate viewController:self.presentingViewController didPresentViewController:self.presentedViewController];
|
||||
}
|
||||
for (NSObject<MVMCorePresentationDelegateProtocol> *delegate in [MVMCoreNavigationHandler sharedNavigationHandler].delegates.allObjects) {
|
||||
if (delegate && [delegate respondsToSelector:@selector(viewController:didPresentViewController:)]) {
|
||||
[delegate viewController:self.presentingViewController didPresentViewController:self.presentedViewController];
|
||||
}
|
||||
}
|
||||
[self markAsFinished];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,20 +0,0 @@
|
||||
//
|
||||
// MVMCorePresentViewControllerOperation.h
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 9/28/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 <Foundation/Foundation.h>
|
||||
//#import <MVMCore/MVMCoreOperation.h>
|
||||
//#import <MVMCore/MVMCorePresentationDelegateProtocol.h>
|
||||
//
|
||||
//@interface MVMCorePresentViewControllerOperation : MVMCoreOperation
|
||||
//
|
||||
//@property (nullable, weak, nonatomic) NSObject<MVMCorePresentationDelegateProtocol> *delegate;
|
||||
//
|
||||
//- (nullable instancetype)initWithPresentingViewController:(nullable UIViewController *)presentingViewController presentedViewController:(nullable UIViewController *)presentedViewController animated:(BOOL)animated;
|
||||
//
|
||||
//@end
|
||||
@ -1,74 +0,0 @@
|
||||
//
|
||||
// MVMCorePresentViewControllerOperation.m
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 9/28/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCorePresentViewControllerOperation.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;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MVMCorePresentViewControllerOperation
|
||||
|
||||
- (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;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@ -9,34 +9,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@protocol MVMCorePresentationDelegateProtocol
|
||||
@protocol MVMCorePresentationDelegateProtocol <UINavigationControllerDelegate>
|
||||
|
||||
@optional
|
||||
// Called when a view controller is about to be added to a navigation controller
|
||||
- (void)navigationController:(nonnull UINavigationController *)navigationController prepareDisplayForViewController:(nonnull UIViewController *)viewController;
|
||||
|
||||
// Called when a view controller will be displayed on a navigation controller
|
||||
- (void)navigationController:(nonnull UINavigationController *)navigationController willDisplayViewController:(nonnull UIViewController *)viewController;
|
||||
|
||||
// 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 <UIViewControllerAnimatedTransitioning>)navigationController:(nonnull UINavigationController *)navigationController
|
||||
animationControllerForOperation:(UINavigationControllerOperation)operation
|
||||
fromViewController:(nonnull UIViewController *)fromVC
|
||||
toViewController:(nonnull UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
|
||||
|
||||
- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(nonnull UINavigationController *)navigationController
|
||||
interactionControllerForAnimationController:(nonnull id <UIViewControllerAnimatedTransitioning>) 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;
|
||||
|
||||
// Called when a view controller did be present on another
|
||||
- (void)viewController:(nonnull UIViewController *)presentingViewController didPresentViewController:(nonnull UIViewController *)presentedViewController;
|
||||
|
||||
@end
|
||||
|
||||
306
MVMCore/MVMCore/PresentationHandling/NavigationHandler.swift
Normal file
306
MVMCore/MVMCore/PresentationHandling/NavigationHandler.swift
Normal file
@ -0,0 +1,306 @@
|
||||
//
|
||||
// NavigationHandler.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Scott Pfeil on 8/29/22.
|
||||
// Copyright © 2022 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
/** Handles UIViewController navigation. Push, pop, present, etc.
|
||||
All navigation should be performed using this handler. Only one navigation can happen at a time to ensure there are no collisions and failures.
|
||||
*/
|
||||
public class NavigationHandler {
|
||||
public enum NavigationType {
|
||||
case push(viewController: UIViewController, navigationController: UINavigationController, animated: Bool = true)
|
||||
case replace(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 popToRoot(navigationController: UINavigationController, animated: Bool = true)
|
||||
case present(viewController: UIViewController, onController: UIViewController, animated: Bool = true)
|
||||
case dismiss(viewController: UIViewController, animated: Bool = true)
|
||||
|
||||
/**
|
||||
- Returns: The navigation controller performing the navigation.
|
||||
*/
|
||||
public func getNavigationController() -> UINavigationController? {
|
||||
switch self {
|
||||
case .push( _, let navigationController, _),
|
||||
.replace( _, let navigationController, _),
|
||||
.set( _, let navigationController, _),
|
||||
.popTo( _, let navigationController, _):
|
||||
return navigationController
|
||||
case .pop(let navigationController, _),
|
||||
.popToRoot(let navigationController, _):
|
||||
return navigationController
|
||||
default:
|
||||
return nil
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static let handler = NavigationHandler()
|
||||
public static func shared() -> NavigationHandler {
|
||||
return handler
|
||||
}
|
||||
|
||||
private init() {}
|
||||
|
||||
/// Can set the view controller to do presentation operations on... otherwise presentation will try to use the rootViewController of the keyWindow ``MVMCoreGetterUtility/getKeyWindow()``
|
||||
public weak var viewControllerToPresentOn: UIViewController?
|
||||
|
||||
/// Convenience setter. Can set the navigationController to do navigation all navigation operations on when none are passed.
|
||||
public weak var navigationController: UINavigationController?
|
||||
|
||||
/// The operationQueue of navigation operations. It's a serial queue.
|
||||
public let navigationQueue: OperationQueue = {
|
||||
var queue = OperationQueue()
|
||||
queue.maxConcurrentOperationCount = 1
|
||||
return queue
|
||||
}()
|
||||
|
||||
// MARK: - Publishers
|
||||
|
||||
/** Publishes when the navigation will begin
|
||||
- Parameter NavigationType: The type of navigation being performed.
|
||||
*/
|
||||
public let onNavigationWillBegin = PassthroughSubject<(NavigationType), Never>()
|
||||
|
||||
/** Publishes when the navigation did finish
|
||||
- Parameter NavigationType: The type of navigation being performed.
|
||||
*/
|
||||
public let onNavigationDidFinish = PassthroughSubject<(NavigationType), Never>()
|
||||
|
||||
// MARK: - Navigation Functions
|
||||
|
||||
/**
|
||||
Adds a navigation operation to the queue.
|
||||
- Parameter operation: The operation to add.
|
||||
*/
|
||||
public func navigate(with operation: Operation) async {
|
||||
await withCheckedContinuation { continuation in
|
||||
operation.completionBlock = {
|
||||
operation.completionBlock = nil
|
||||
continuation.resume()
|
||||
}
|
||||
navigationQueue.addOperation(operation)
|
||||
} as Void
|
||||
}
|
||||
|
||||
/**
|
||||
Navigates with the navigation type..
|
||||
- Parameter type: The type of navigation to perform.
|
||||
- Parameter tryToReplace: If the view controller is already in the navigation history, do we replace it.
|
||||
- Parameter delegateObject: A delegate object for various delegations.
|
||||
*/
|
||||
public func navigate(with type: NavigationType, tryToReplace: Bool = true, delegateObject: DelegateObject? = nil) async {
|
||||
let operation = await NavigationOperation(with: type, tryToReplace: tryToReplace, delegate: delegateObject?.presentationDelegate)
|
||||
await navigate(with: operation)
|
||||
}
|
||||
|
||||
/**
|
||||
The base view controller for presentation when none are passed in.
|
||||
Either the convenience ``viewControllerToPresentOn`` or the rootViewController of the window ``MVMCoreGetterUtility/getKeyWindow()``
|
||||
- Returns: The base view controller for presentation.
|
||||
*/
|
||||
@MainActor
|
||||
public func getViewControllerToPresentOn() -> UIViewController? {
|
||||
return viewControllerToPresentOn ?? MVMCoreGetterUtility.getKeyWindow()?.rootViewController
|
||||
}
|
||||
|
||||
/**
|
||||
Get the top most presented view controller to present on.
|
||||
Loops through presentedViewController on ``getViewControllerToPresentOn()``
|
||||
- Returns: The top most view controller to present on.
|
||||
*/
|
||||
@MainActor
|
||||
public func getTopMostPresentedViewController() -> UIViewController? {
|
||||
var viewController = getViewControllerToPresentOn()?.presentedViewController
|
||||
while let presentedController = viewController?.presentedViewController {
|
||||
viewController = presentedController
|
||||
}
|
||||
return viewController
|
||||
}
|
||||
|
||||
public func push(viewController: UIViewController, navigationController: UINavigationController? = nil, delegateObject: DelegateObject? = nil, animated: Bool = true) async {
|
||||
guard let navigationController = navigationController ?? self.navigationController else { return }
|
||||
await NavigationHandler.shared().navigate(with: .push(viewController: viewController, navigationController: navigationController, animated: animated), delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
public func replace(viewController: UIViewController, navigationController: UINavigationController? = nil, delegateObject: DelegateObject? = nil, tryToReplace: Bool = true, animated: Bool = true) async {
|
||||
guard let navigationController = navigationController ?? self.navigationController else { return }
|
||||
await NavigationHandler.shared().navigate(with: .replace(viewController: viewController, navigationController: navigationController, animated: animated), delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
public func set(viewControllers: [UIViewController], navigationController: UINavigationController? = nil, delegateObject: DelegateObject? = nil, animated: Bool = true) async {
|
||||
guard let navigationController = navigationController ?? self.navigationController else { return }
|
||||
await NavigationHandler.shared().navigate(with: .set(viewControllers: viewControllers, navigationController: navigationController, animated: animated), delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
public func popTopViewController(navigationController: UINavigationController? = nil, delegateObject: DelegateObject? = nil, animated: Bool = true) async {
|
||||
guard let navigationController = navigationController ?? self.navigationController else { return }
|
||||
await navigate(with: .pop(navigationController: navigationController, animated: animated), delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
public func present(viewController: UIViewController, delegateObject: DelegateObject? = nil, animated: Bool = true) async {
|
||||
guard let viewControllerToPresentOn = await getViewControllerToPresentOn() else { return }
|
||||
await navigate(with: .present(viewController: viewController, onController: viewControllerToPresentOn, animated: animated), delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
public func dismissTopViewController(delegateObject: DelegateObject? = nil, animated: Bool = true) async {
|
||||
guard let presentedViewController = await getTopMostPresentedViewController() else { return }
|
||||
await navigate(with: .dismiss(viewController: presentedViewController), delegateObject: delegateObject)
|
||||
}
|
||||
|
||||
public func removeCurrentViewController(delegateObject: DelegateObject? = nil, animated: Bool = true) async {
|
||||
if let presentedViewController = await getTopMostPresentedViewController() {
|
||||
if let navigationController = (presentedViewController as? UINavigationController),
|
||||
await navigationController.viewControllers.count > 1 {
|
||||
await navigate(with: .pop(navigationController: navigationController, animated: animated), delegateObject: delegateObject)
|
||||
} else {
|
||||
await navigate(with: .dismiss(viewController: presentedViewController, animated: animated), delegateObject: delegateObject)
|
||||
}
|
||||
} else if let navigationController = navigationController {
|
||||
await navigate(with: .pop(navigationController: navigationController, animated: animated), delegateObject: delegateObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UINavigationController {
|
||||
/**
|
||||
- Parameter pageType: The pageType of the viewController to search for.
|
||||
- Returns: The index in of the view controller with the pageType in viewControllers.
|
||||
*/
|
||||
func getIndexOfViewController(with pageType: String) -> Int? {
|
||||
return viewControllers.firstIndex { viewController in
|
||||
(viewController as? MVMCoreViewControllerProtocol)?.pageType == pageType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UIViewController {
|
||||
/**
|
||||
Get the top most presented view controller to present on.
|
||||
Loops through presentedViewController on self.
|
||||
- Returns: The top most view controller to present on.
|
||||
*/
|
||||
func getViewControllerToPresentOn() -> UIViewController {
|
||||
var controllerToPresentOn = self
|
||||
while let presentedController = controllerToPresentOn.presentedViewController {
|
||||
controllerToPresentOn = presentedController
|
||||
}
|
||||
return controllerToPresentOn
|
||||
}
|
||||
}
|
||||
|
||||
/// Legacy objc ``NavigationHandler`` wrapper.
|
||||
@objc public class MVMCoreNavigationHandler: NSObject {
|
||||
|
||||
@objc(sharedNavigationHandler)
|
||||
public static func shared() -> MVMCoreNavigationHandler? {
|
||||
return MVMCoreNavigationHandler()
|
||||
}
|
||||
|
||||
@objc
|
||||
public weak var viewControllerToPresentOn: UIViewController? {
|
||||
get {
|
||||
return NavigationHandler.shared().viewControllerToPresentOn
|
||||
}
|
||||
set {
|
||||
NavigationHandler.shared().viewControllerToPresentOn = newValue
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public func popTopViewControllerAnimated(_ animated: Bool) {
|
||||
Task(priority: .high) { @MainActor in
|
||||
await NavigationHandler.shared().popTopViewController()
|
||||
}
|
||||
}
|
||||
|
||||
@objc(presentViewController:animated:)
|
||||
public func present(_ viewController: UIViewController, animated: Bool) {
|
||||
Task(priority: .high) { @MainActor in
|
||||
await NavigationHandler.shared().present(viewController: viewController, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
@objc(dismissTopViewControllerAnimated:)
|
||||
public func dismissTopViewController(animated: Bool) {
|
||||
Task(priority: .high) { @MainActor in
|
||||
await NavigationHandler.shared().dismissTopViewController(animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public func popToViewControllerWithPageType(_ pageType: String, navigationController: UINavigationController?, animated: Bool = true, delegate: MVMCorePresentationDelegateProtocol?, completionHandler:(() -> Void)?) {
|
||||
Task(priority: .high) { @MainActor in
|
||||
guard let navigationController = navigationController ?? NavigationHandler.shared().navigationController,
|
||||
let viewController = navigationController.viewControllers.first(where: { viewController in
|
||||
(viewController as? MVMCoreViewControllerProtocol)?.pageType == pageType
|
||||
}) else {
|
||||
completionHandler?()
|
||||
return
|
||||
}
|
||||
await NavigationHandler.shared().navigate(with: .popTo(viewController: viewController, navigationController: navigationController, animated: animated))
|
||||
completionHandler?()
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public func navigateWithLoadObject(_ loadObject: MVMCoreLoadObject?, viewController: UIViewController, delegate: MVMCorePresentationDelegateProtocol?, completionHandler:(() -> Void)?) {
|
||||
Task(priority: .high) {
|
||||
let delegateObject = DelegateObject()
|
||||
delegateObject.presentationDelegate = delegate
|
||||
guard let requestParameters = loadObject?.requestParameters else {
|
||||
// Push
|
||||
await NavigationHandler.shared().push(viewController:viewController, delegateObject:delegateObject, animated:true)
|
||||
completionHandler?()
|
||||
return
|
||||
}
|
||||
let shouldAnimate = !requestParameters.shouldNotAnimatePush
|
||||
let navigationController = requestParameters.navigationController ?? NavigationHandler.shared().navigationController
|
||||
switch requestParameters.loadStyle {
|
||||
case .replaceCurrent:
|
||||
await NavigationHandler.shared().replace(viewController: viewController, navigationController: navigationController, delegateObject: delegateObject, animated: shouldAnimate)
|
||||
completionHandler?()
|
||||
case .onTopOfRoot:
|
||||
guard let root = await navigationController?.viewControllers.first else { return }
|
||||
let viewControllers = [root, viewController]
|
||||
await NavigationHandler.shared().set(viewControllers: viewControllers, navigationController: navigationController, delegateObject: delegateObject, animated: shouldAnimate)
|
||||
completionHandler?()
|
||||
case .becomeRoot:
|
||||
await NavigationHandler.shared().set(viewControllers: [viewController], navigationController: navigationController, delegateObject: delegateObject, animated: shouldAnimate)
|
||||
completionHandler?()
|
||||
case .present:
|
||||
await NavigationHandler.shared().present(viewController: viewController, animated: shouldAnimate)
|
||||
completionHandler?()
|
||||
default:
|
||||
await NavigationHandler.shared().push(viewController: viewController, navigationController: navigationController, delegateObject: delegateObject, animated: shouldAnimate)
|
||||
completionHandler?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the viewControllers of the navigation controller.
|
||||
Takes into account the current animation state ``NavigationOperation/toNavigationControllerViewControllers``
|
||||
- Parameter navigationController: The navigation controller to fetch the viewcontrollers for.
|
||||
- Returns: The viewControllers.
|
||||
*/
|
||||
@objc(getViewControllersForNavigationController:)
|
||||
public func getViewControllers(for navigationController: UINavigationController) -> [UIViewController] {
|
||||
// Check if we are currently animating.
|
||||
guard let operation = NavigationHandler.shared().navigationQueue.operations.first(where: { operation in
|
||||
operation.isExecuting && (operation as? NavigationOperation) != nil
|
||||
}) as? NavigationOperation,
|
||||
navigationController == operation.navigationType.getNavigationController(),
|
||||
let futureViewControllers = operation.toNavigationControllerViewControllers
|
||||
else { return navigationController.viewControllers }
|
||||
return futureViewControllers
|
||||
}
|
||||
}
|
||||
229
MVMCore/MVMCore/PresentationHandling/NavigationOperation.swift
Normal file
229
MVMCore/MVMCore/PresentationHandling/NavigationOperation.swift
Normal file
@ -0,0 +1,229 @@
|
||||
//
|
||||
// NavigationOperation.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Scott Pfeil on 8/14/23.
|
||||
// Copyright © 2023 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
/// An operation for the navigation.
|
||||
open class NavigationOperation: MVMCoreOperation, UINavigationControllerDelegate {
|
||||
open var navigationType: NavigationHandler.NavigationType
|
||||
open var tryToReplace: Bool
|
||||
open var delegate: MVMCorePresentationDelegateProtocol?
|
||||
|
||||
/// The pending state of the navigation controllers viewcontroller stack.
|
||||
open var toNavigationControllerViewControllers: [UIViewController]?
|
||||
|
||||
private var cancellable: Cancellable?
|
||||
|
||||
public init(with navigationType: NavigationHandler.NavigationType, tryToReplace: Bool = true, delegate: MVMCorePresentationDelegateProtocol? = nil) {
|
||||
self.navigationType = navigationType
|
||||
self.tryToReplace = tryToReplace
|
||||
self.delegate = delegate
|
||||
super.init()
|
||||
}
|
||||
|
||||
open override func main() {
|
||||
checkAndHandleForCancellation()
|
||||
Task(priority: .high) { @MainActor in
|
||||
try Task.checkCancellation()
|
||||
|
||||
switch navigationType {
|
||||
case .push(let viewController, let navigationController, let animated):
|
||||
push(viewController: viewController, navigationController: navigationController, animated: animated)
|
||||
case .replace(let viewController, let navigationController, let animated):
|
||||
replace(viewController: viewController, navigationController: navigationController, animated: animated)
|
||||
case .set(let viewControllers, let navigationController, let animated):
|
||||
set(viewControllers: viewControllers, navigationController: navigationController, animated: animated)
|
||||
case .pop(let navigationController, let animated):
|
||||
pop(navigationController: navigationController, animated: animated)
|
||||
case .popTo(let viewController, let navigationController, let animated):
|
||||
popTo(viewController: viewController, navigationController: navigationController, animated: animated)
|
||||
case .popToRoot(let navigationController, let animated):
|
||||
popToRoot(navigationController: navigationController, animated: animated)
|
||||
case .present(let viewController, let onController, let animated):
|
||||
present(viewController: viewController, onController: onController, animated: animated)
|
||||
case .dismiss(let viewController, let animated):
|
||||
dismiss(viewController: viewController, animated: animated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Navigation
|
||||
|
||||
/** Checks if a view controller with the same pageType already exists in the navigation hiearchy. If so, replace it and pop back to it.
|
||||
- Parameter viewController: The viewcontroller to add to the navigation hierarchy.
|
||||
- Parameter navigationController: The navigationcontroller to add to the viewcontroller to.
|
||||
- Parameter animated: If the transition should be animated.
|
||||
- Returns: If the pageType already exists in the stack and it will be replaced.
|
||||
*/
|
||||
@MainActor
|
||||
open func tryToReplace(viewController: UIViewController, navigationController: UINavigationController, animated: Bool) -> Bool {
|
||||
guard tryToReplace,
|
||||
let pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType,
|
||||
let index = navigationController.getIndexOfViewController(with: pageType) else {
|
||||
return false
|
||||
}
|
||||
var viewControllers = navigationController.viewControllers[...index]
|
||||
viewControllers[index] = viewController
|
||||
set(viewControllers: Array(viewControllers), navigationController: navigationController, animated: animated)
|
||||
return true
|
||||
}
|
||||
|
||||
/** Has the navigation controller add the view controller.
|
||||
Checks for ``tryToReplace(viewController:navigationController:animated:)`` first.
|
||||
- Parameter viewController: The viewcontroller to add to the navigation hierarchy.
|
||||
- Parameter navigationController: The navigationcontroller to add to the viewcontroller to.
|
||||
- Parameter animated: If the transition should be animated.
|
||||
*/
|
||||
@MainActor
|
||||
open func push(viewController: UIViewController, navigationController: UINavigationController, animated: Bool) {
|
||||
guard !tryToReplace(viewController: viewController, navigationController: navigationController, animated: animated) else { return }
|
||||
var viewControllers = navigationController.viewControllers
|
||||
viewControllers.append(viewController)
|
||||
set(viewControllers: viewControllers, navigationController: navigationController, animated: animated)
|
||||
}
|
||||
|
||||
/** Has the navigation controller replace the topViewController with the view controller.
|
||||
Checks for ``tryToReplace(viewController:navigationController:animated:)`` first.
|
||||
- Parameter viewController: The viewcontroller to add to the navigation hierarchy.
|
||||
- Parameter navigationController: The navigationcontroller to add to the viewcontroller to.
|
||||
- Parameter animated: If the transition should be animated.
|
||||
*/
|
||||
@MainActor
|
||||
open func replace(viewController: UIViewController, navigationController: UINavigationController, animated: Bool) {
|
||||
guard !tryToReplace(viewController: viewController, navigationController: navigationController, animated: animated) else { return }
|
||||
var viewControllers = navigationController.viewControllers
|
||||
viewControllers.removeLast()
|
||||
viewControllers.append(viewController)
|
||||
set(viewControllers: viewControllers, navigationController: navigationController, animated: animated)
|
||||
}
|
||||
|
||||
/** Has the navigation controller set the view controllers.
|
||||
- Parameter viewControllers: The viewcontrollers to set the navigation hierarchy to.
|
||||
- Parameter navigationController: The navigationcontroller to set the viewcontrollers for.
|
||||
- Parameter animated: If the transition should be animated.
|
||||
*/
|
||||
@MainActor
|
||||
open func set(viewControllers: [UIViewController], navigationController: UINavigationController, animated: Bool) {
|
||||
guard viewControllers.count > 0 else {
|
||||
markAsFinished()
|
||||
return
|
||||
}
|
||||
navigationController.delegate = self
|
||||
toNavigationControllerViewControllers = viewControllers
|
||||
NavigationHandler.shared().onNavigationWillBegin.send(navigationType)
|
||||
navigationController.setViewControllers(viewControllers, animated: animated)
|
||||
}
|
||||
|
||||
/** Has the navigation controller pop.
|
||||
- Parameter navigationController: The navigationcontroller to perform the pop.
|
||||
- Parameter animated: If the transition should be animated.
|
||||
*/
|
||||
@MainActor
|
||||
open func pop(navigationController: UINavigationController, animated: Bool) {
|
||||
guard navigationController.viewControllers.count > 1 else {
|
||||
markAsFinished()
|
||||
return
|
||||
}
|
||||
var viewControllers = navigationController.viewControllers
|
||||
viewControllers.removeLast()
|
||||
set(viewControllers: viewControllers, navigationController: navigationController, animated: animated)
|
||||
}
|
||||
|
||||
/** Has the navigation controller pop to a specific view controller.
|
||||
- Parameter viewController: The viewcontroller to pop to.
|
||||
- Parameter navigationController: The navigationcontroller to perform the pop.
|
||||
- Parameter animated: If the transition should be animated.
|
||||
*/
|
||||
@MainActor
|
||||
open func popTo(viewController: UIViewController, navigationController: UINavigationController, animated: Bool) {
|
||||
guard navigationController.viewControllers.count > 1,
|
||||
let index = navigationController.viewControllers.firstIndex(of: viewController),
|
||||
index != navigationController.viewControllers.count - 1 else {
|
||||
markAsFinished()
|
||||
return
|
||||
}
|
||||
let viewControllers = Array(navigationController.viewControllers[...index])
|
||||
set(viewControllers: viewControllers, navigationController: navigationController, animated: animated)
|
||||
}
|
||||
|
||||
/** Has the navigation controller pop to root.
|
||||
- Parameter navigationController: The navigationcontroller to perform the pop.
|
||||
- Parameter animated: If the transition should be animated.
|
||||
*/
|
||||
@MainActor
|
||||
open func popToRoot(navigationController: UINavigationController, animated: Bool) {
|
||||
guard navigationController.viewControllers.count > 1 else {
|
||||
markAsFinished()
|
||||
return
|
||||
}
|
||||
let viewController = navigationController.viewControllers.first!
|
||||
set(viewControllers: [viewController], navigationController: navigationController, animated: animated)
|
||||
}
|
||||
|
||||
/** Presents the viewcontroller.
|
||||
The viewcontroller is presented on the top most presented controller of the onController because Apple does not allow a controller to present more than one.
|
||||
- Parameter viewController: The viewcontroller to present.
|
||||
- Parameter onController: The controller to perform the present on. Iterates presentedViewController to find the top most.
|
||||
- Parameter animated: If the transition should be animated.
|
||||
*/
|
||||
@MainActor
|
||||
open func present(viewController: UIViewController, onController: UIViewController, animated: Bool = true) {
|
||||
NavigationHandler.shared().onNavigationWillBegin.send(navigationType)
|
||||
onController.getViewControllerToPresentOn().present(viewController, animated: animated) { [self] in
|
||||
NavigationHandler.shared().onNavigationDidFinish.send(navigationType)
|
||||
markAsFinished()
|
||||
}
|
||||
}
|
||||
|
||||
/** Dismisses the viewcontroller.
|
||||
- Parameter viewController: The viewcontroller to dismiss.
|
||||
- Parameter animated: If the transition should be animated.
|
||||
*/
|
||||
@MainActor
|
||||
open func dismiss(viewController: UIViewController, animated: Bool = true) {
|
||||
NavigationHandler.shared().onNavigationWillBegin.send(navigationType)
|
||||
viewController.dismiss(animated: animated) { [self] in
|
||||
NavigationHandler.shared().onNavigationDidFinish.send(navigationType)
|
||||
markAsFinished()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UINavigationControllerDelegate
|
||||
|
||||
open func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
|
||||
delegate?.navigationController?(navigationController, didShow: viewController, animated: animated)
|
||||
NavigationHandler.shared().onNavigationDidFinish.send(navigationType)
|
||||
markAsFinished()
|
||||
}
|
||||
|
||||
open func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
|
||||
delegate?.navigationController?(navigationController, willShow: viewController, animated: animated)
|
||||
}
|
||||
|
||||
open func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||||
delegate?.navigationController?(navigationController, interactionControllerFor: animationController)
|
||||
}
|
||||
|
||||
open func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
let animatedTransitioning = delegate?.navigationController?(navigationController, animationControllerFor: operation, from: fromVC, to: toVC)
|
||||
guard let animatedTransitioning = animatedTransitioning as? MVMCoreViewControllerAnimatedTransitioning & NSObject else { return animatedTransitioning }
|
||||
cancellable = animatedTransitioning
|
||||
.kvoPublisher(for: "interactiveTransitionCanceled", type: Bool.self)
|
||||
.sink(receiveValue: { [weak self] value in
|
||||
guard value == true else { return }
|
||||
// When the interactive transition is cancelled, the destination viewController should be removed.
|
||||
if operation == .push {
|
||||
toVC.removeFromParent()
|
||||
}
|
||||
self?.delegate?.navigationController?(navigationController, interactiveTransitionWasCanceled: true)
|
||||
self?.cancel()
|
||||
})
|
||||
return animatedTransitioning
|
||||
}
|
||||
}
|
||||
65
MVMCore/MVMCore/Utility/Helpers/KVOPublisher.swift
Normal file
65
MVMCore/MVMCore/Utility/Helpers/KVOPublisher.swift
Normal file
@ -0,0 +1,65 @@
|
||||
//
|
||||
// KVOPublisher.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Scott Pfeil on 8/14/23.
|
||||
// Copyright © 2023 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
public struct KVOPublisher<ObjectType: NSObject, ValueType>: Publisher {
|
||||
public typealias Output = ValueType
|
||||
public typealias Failure = Never
|
||||
|
||||
private let object: ObjectType
|
||||
private let keyPath: String
|
||||
private let options: NSKeyValueObservingOptions
|
||||
|
||||
public init(object: ObjectType, keyPath: String, options: NSKeyValueObservingOptions = [.new]) {
|
||||
self.object = object
|
||||
self.keyPath = keyPath
|
||||
self.options = options
|
||||
}
|
||||
|
||||
public func receive<S: Subscriber>(subscriber: S) where ValueType == S.Input, Never == S.Failure {
|
||||
let subscription = KVOSubscription(subscriber: subscriber, object: object, keyPath: keyPath, options: options)
|
||||
subscriber.receive(subscription: subscription)
|
||||
}
|
||||
|
||||
private final class KVOSubscription<S: Subscriber, ObjectType: NSObject, ValueType>:NSObject, Subscription where S.Input == ValueType {
|
||||
private let subscriber: S
|
||||
private var object: ObjectType
|
||||
private var keyPath: String
|
||||
private var options: NSKeyValueObservingOptions
|
||||
|
||||
init(subscriber: S, object: ObjectType, keyPath: String, options: NSKeyValueObservingOptions = [.new]) {
|
||||
self.object = object
|
||||
self.keyPath = keyPath
|
||||
self.options = options
|
||||
self.subscriber = subscriber
|
||||
super.init()
|
||||
self.object.addObserver(self, forKeyPath: self.keyPath, options: options, context: nil)
|
||||
}
|
||||
|
||||
func request(_ demand: Subscribers.Demand) {}
|
||||
func cancel() {}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == self.keyPath, let change = change, let newValue = change[.newKey] as? ValueType {
|
||||
_ = subscriber.receive(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.object.removeObserver(self, forKeyPath: keyPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NSObject {
|
||||
public func kvoPublisher<Value>(for keyPath: String, type: Value.Type, options: NSKeyValueObservingOptions = [.new]) -> AnyPublisher<Value, Never> {
|
||||
return KVOPublisher(object: self, keyPath: keyPath, options: options).eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@
|
||||
#import "NSDictionary+MFConvenience.h"
|
||||
#import "MVMCoreJSONConstants.h"
|
||||
#import "MVMCoreObject.h"
|
||||
#import "MVMCoreNavigationHandler.h"
|
||||
#import <MVMCore/MVMCore-Swift.h>
|
||||
|
||||
@implementation MVMCoreActionUtility
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user