ONEAPP-5208: Swiftify the navigation handler

This commit is contained in:
Scott Pfeil 2023-08-21 17:03:47 -04:00
parent 6877763d07
commit 64535c6b21
10 changed files with 242 additions and 176 deletions

View File

@ -97,6 +97,7 @@
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 */; };
AF686FDE2A8D29CD008F666A /* MVMCoreLoadRequestOperation+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF686FDD2A8D29CD008F666A /* MVMCoreLoadRequestOperation+Extension.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 */; };
@ -252,6 +253,7 @@
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>"; };
AF686FDD2A8D29CD008F666A /* MVMCoreLoadRequestOperation+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreLoadRequestOperation+Extension.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>"; };
@ -562,6 +564,7 @@
AFBB964B1FBA3A560008D868 /* MVMCoreLoadHandler.m */,
AFBB964A1FBA3A560008D868 /* MVMCoreLoadRequestOperation.h */,
AFBB96521FBA3A570008D868 /* MVMCoreLoadRequestOperation.m */,
AF686FDD2A8D29CD008F666A /* MVMCoreLoadRequestOperation+Extension.swift */,
AFBB96471FBA3A560008D868 /* MVMCoreLoadObject.h */,
AFBB96481FBA3A560008D868 /* MVMCoreLoadObject.m */,
AFBB96491FBA3A560008D868 /* MVMCoreRequestParameters.h */,
@ -935,6 +938,7 @@
AF69D4F1286E9D8000BC6862 /* ActionNoopHandler.swift in Sources */,
016FF6F2259A4FCC00F5E4AA /* ClientParameterModel.swift in Sources */,
D2DEDCBB23C65BC300C44CC4 /* Percent.swift in Sources */,
AF686FDE2A8D29CD008F666A /* MVMCoreLoadRequestOperation+Extension.swift in Sources */,
60CBD0542A02397A00056CB0 /* MVMCoreSessionTimeHandler.swift in Sources */,
AF686FDC2A8A87EA008F666A /* KVOPublisher.swift in Sources */,
AFBB966A1FBA3A570008D868 /* MVMCoreLoadRequestOperation.m in Sources */,

View File

@ -7,6 +7,7 @@
//
import Foundation
open class ActionShareHandler: MVMCoreActionHandlerProtocol {
required public init() {}
@ -28,7 +29,7 @@ open class ActionShareHandler: MVMCoreActionHandlerProtocol {
open func shareWith(activityItems: [Any], model: ActionShareModel, delegateObject: DelegateObject? = nil) async throws {
try await withCheckedThrowingContinuation { continuation in
let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
controller.popoverPresentationController?.sourceView = MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn?.view
controller.popoverPresentationController?.sourceView = NavigationHandler.shared().viewControllerToPresentOn?.view
controller.completionWithItemsHandler = {(activityType: UIActivity.ActivityType?, completed: Bool, returnedItems: [Any]?, error: Error?) in
if completed {
// Activity was completed, considered finished.

View File

@ -0,0 +1,91 @@
//
// MVMCoreLoadRequestOperation+Extension.swift
// MVMCore
//
// Created by Scott Pfeil on 8/16/23.
// Copyright © 2023 myverizon. All rights reserved.
//
import Foundation
public enum PopBackError: MVMError, CustomStringConvertible {
case noPageType
case noNavigationHandler
case noViewController
public var description: String {
switch self {
case .noPageType:
return "Cannot pop with a pageType."
case .noNavigationHandler:
return "Cannot pop with a navigation controller."
case .noViewController:
return "No View Controller of popBackPageType in the hierarchy"
}
}
public var errorCode: Int {
switch self {
case .noPageType:
return 55
case .noNavigationHandler:
return 56
case .noViewController:
return 57
}
}
}
@objc
public extension MVMCoreLoadRequestOperation {
@objc
func popBackToPage(for loadObject: MVMCoreLoadObject) {
Task(priority: .high) {
do {
guard let popBackPageType = loadObject.pageJSON?.optionalStringForKey("popBackPageType") else {
throw PopBackError.noPageType
}
try await NavigationHandler.shared().popToViewController(with: popBackPageType, navigationController: loadObject.requestParameters?.navigationController, delegateObject: loadObject.delegateObject, animated: !(loadObject.requestParameters?.shouldNotAnimatePush ?? false))
MVMCoreLoadRequestOperation.loadFinished(loadObject, loadedViewController: nil, errorObject: nil)
} catch {
MVMCoreLoadRequestOperation.loadFinished(loadObject, loadedViewController: nil, errorObject: MVMCoreErrorObject.createErrorObject(for: error, location: MVMCoreLoadHandler.sharedGlobal()?.errorLocation(forRequest: loadObject)))
}
}
}
@objc
func display(viewController: UIViewController, loadObject: MVMCoreLoadObject?, completionHandler: @escaping () -> Void) {
Task(priority: .high) {
guard let navigationOperation = await NavigationHandler.shared().getNavigationOperation(with: viewController, loadObject: loadObject) else {
completionHandler()
return
}
// stop any loading animation we may have started if we are about to display
cancellable = NavigationHandler.shared().onNavigationWillBegin.sink(receiveValue: { operation in
if navigationOperation == operation,
!self.backgroundLoad,
!(loadObject?.requestParameters?.noloadingOverlay ?? false) {
MVMCoreLoadingOverlayHandler.sharedLoadingOverlay()?.stopLoading(false)
}
})
await NavigationHandler.shared().navigate(with: navigationOperation)
cancellable = nil
completionHandler()
}
}
}
public extension NavigationHandler {
func popToViewController(with pageType: String, navigationController: UINavigationController? = nil, delegateObject: DelegateObject? = nil, animated: Bool = true) async throws {
guard let navigationController = navigationController ?? NavigationHandler.shared().navigationController else {
throw PopBackError.noNavigationHandler
}
guard let viewController = await navigationController.viewControllers.first(where: { viewController in
(viewController as? MVMCoreViewManagerProtocol)?.containsPage(withPageType: pageType) == true ||
(viewController as? MVMCoreViewControllerProtocol)?.pageType == pageType
}) else {
throw PopBackError.noViewController
}
await NavigationHandler.shared().navigate(with: .popTo(viewController: viewController, navigationController: navigationController, animated: animated), delegateObject: delegateObject)
}
}

View File

@ -31,6 +31,8 @@
/// Legacy flag for if this operation will have an alert to show when finished.
@property (nonatomic, readonly) BOOL alertToShow;
@property (nullable, strong, nonatomic) id cancellable;
// Initializes the operation with the request parameters object, data for page, and mvm view controller to handle the loading with.
- (nullable instancetype)initWithRequestParameters:(nullable MVMCoreRequestParameters *)requestParameters dataForPage:(nullable NSDictionary *)dataForPage delegateObject:(nullable DelegateObject *)delegateObject backgroundLoad:(BOOL)backgroundLoad;

View File

@ -482,9 +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.delegateObject.presentationDelegate completionHandler:^{
[MVMCoreLoadRequestOperation loadFinished:loadObject loadedViewController:nil errorObject:error];
}];
[loadObject.operation popBackToPageFor:loadObject];
// Notify listeners of module/pages loaded.
[MVMCoreLoadRequestOperation notifyListenersOfNewResponse:pages modules:modules systemParameters:systemParameters loadObject:loadObject];
@ -776,7 +774,7 @@
}
// Once displyed, we are finished.
[MVMCoreActionUtility displayViewController:viewController forLoadObject:loadObject presentationDelegate:loadObject.delegateObject.presentationDelegate completionHandler:^{
[loadObject.operation displayWithViewController:viewController loadObject:loadObject completionHandler:^{
[MVMCoreLoadRequestOperation loadFinished:loadObject loadedViewController:viewController errorObject:error];
}];
}

View File

@ -68,12 +68,56 @@ public class NavigationHandler {
/** Publishes when the navigation will begin
- Parameter NavigationType: The type of navigation being performed.
*/
public let onNavigationWillBegin = PassthroughSubject<(NavigationType), Never>()
public let onNavigationWillBegin = PassthroughSubject<(NavigationOperation), Never>()
/** Publishes when the navigation did finish
- Parameter NavigationType: The type of navigation being performed.
*/
public let onNavigationDidFinish = PassthroughSubject<(NavigationType), Never>()
public let onNavigationDidFinish = PassthroughSubject<(NavigationOperation), Never>()
// MARK: - Getters
/**
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
}
/**
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.
*/
@MainActor
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
}
// MARK: - Navigation Functions
@ -102,30 +146,6 @@ public class NavigationHandler {
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)
@ -182,6 +202,15 @@ extension UINavigationController {
}
}
@objc
public extension UINavigationController {
/// See ``NavigationHandler/getViewControllers(for:)``
@objc @MainActor
func getViewControllers() -> [UIViewController] {
NavigationHandler.shared().getViewControllers(for: self)
}
}
extension UIViewController {
/**
Get the top most presented view controller to present on.
@ -196,111 +225,3 @@ extension UIViewController {
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
}
}

View File

@ -28,7 +28,7 @@ open class NavigationOperation: MVMCoreOperation, UINavigationControllerDelegate
}
open override func main() {
checkAndHandleForCancellation()
guard !checkAndHandleForCancellation() else { return }
Task(priority: .high) { @MainActor in
try Task.checkCancellation()
@ -116,7 +116,8 @@ open class NavigationOperation: MVMCoreOperation, UINavigationControllerDelegate
}
navigationController.delegate = self
toNavigationControllerViewControllers = viewControllers
NavigationHandler.shared().onNavigationWillBegin.send(navigationType)
NavigationHandler.shared().onNavigationWillBegin.send(self)
guard !checkAndHandleForCancellation() else { return }
navigationController.setViewControllers(viewControllers, animated: animated)
}
@ -174,9 +175,10 @@ open class NavigationOperation: MVMCoreOperation, UINavigationControllerDelegate
*/
@MainActor
open func present(viewController: UIViewController, onController: UIViewController, animated: Bool = true) {
NavigationHandler.shared().onNavigationWillBegin.send(navigationType)
NavigationHandler.shared().onNavigationWillBegin.send(self)
guard !checkAndHandleForCancellation() else { return }
onController.getViewControllerToPresentOn().present(viewController, animated: animated) { [self] in
NavigationHandler.shared().onNavigationDidFinish.send(navigationType)
NavigationHandler.shared().onNavigationDidFinish.send(self)
markAsFinished()
}
}
@ -187,9 +189,10 @@ open class NavigationOperation: MVMCoreOperation, UINavigationControllerDelegate
*/
@MainActor
open func dismiss(viewController: UIViewController, animated: Bool = true) {
NavigationHandler.shared().onNavigationWillBegin.send(navigationType)
NavigationHandler.shared().onNavigationWillBegin.send(self)
guard !checkAndHandleForCancellation() else { return }
viewController.dismiss(animated: animated) { [self] in
NavigationHandler.shared().onNavigationDidFinish.send(navigationType)
NavigationHandler.shared().onNavigationDidFinish.send(self)
markAsFinished()
}
}
@ -198,7 +201,7 @@ open class NavigationOperation: MVMCoreOperation, UINavigationControllerDelegate
open func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
delegate?.navigationController?(navigationController, didShow: viewController, animated: animated)
NavigationHandler.shared().onNavigationDidFinish.send(navigationType)
NavigationHandler.shared().onNavigationDidFinish.send(self)
markAsFinished()
}

View File

@ -17,3 +17,79 @@ public extension MVMCoreActionUtility {
return instance
}
}
@objc public extension MVMCoreActionUtility {
/// Can call to display a view controller based on the load object in the same way the architecture does it. Will check the presentation style of the page, action, and request. Will check if needs a view manager.
@objc(displayViewController:forLoadObject:completionHandler:)
static func display(_ viewController: UIViewController & MVMCoreViewControllerProtocol, for loadObject: MVMCoreLoadObject?, completionHandler: (() -> Void)?) {
Task(priority: .high) {
guard let navigationOperation = await NavigationHandler.shared().getNavigationOperation(with: viewController, loadObject: loadObject) else {
completionHandler?()
return
}
await NavigationHandler.shared().navigate(with: navigationOperation)
completionHandler?()
}
}
}
public extension NavigationHandler {
/// Gets the navigation operation based on the requestParameters.
@MainActor
func getNavigationOperation(with requestParameters: MVMCoreRequestParameters, viewController: UIViewController, delegateObject: DelegateObject?) -> NavigationOperation? {
// Lets the server determine the presentation style if not explicitely set by developer.
if requestParameters.loadStyle == .default,
let presentationStyle = requestParameters.actionMap?.optionalStringForKey(KeyPresentationStyle) {
// Sets it based on the action map.
requestParameters.setMFLoadStyleBasedOnPresentationStyle(presentationStyle)
}
let shouldAnimate = !requestParameters.shouldNotAnimatePush
switch requestParameters.loadStyle {
case .replaceCurrent:
guard let navigationController = requestParameters.navigationController ?? NavigationHandler.shared().navigationController else { return nil }
return NavigationOperation(with: .replace(viewController: viewController, navigationController: navigationController, animated: shouldAnimate), tryToReplace: true, delegate: delegateObject?.presentationDelegate)
case .onTopOfRoot:
guard let navigationController = requestParameters.navigationController ?? NavigationHandler.shared().navigationController,
let root = navigationController.viewControllers.first else { return nil }
let viewControllers = [root, viewController]
return NavigationOperation(with: .set(viewControllers: viewControllers, navigationController: navigationController, animated: shouldAnimate), tryToReplace: true, delegate: delegateObject?.presentationDelegate)
case .becomeRoot:
guard let navigationController = requestParameters.navigationController ?? NavigationHandler.shared().navigationController else { return nil }
return NavigationOperation(with: .set(viewControllers: [viewController], navigationController: navigationController, animated: shouldAnimate), tryToReplace: true, delegate: delegateObject?.presentationDelegate)
case .present:
guard let viewControllerToPresentOn = getViewControllerToPresentOn() else { return nil }
return NavigationOperation(with: .present(viewController: viewController, onController: viewControllerToPresentOn, animated: shouldAnimate), tryToReplace: true, delegate: delegateObject?.presentationDelegate)
default:
guard let navigationController = requestParameters.navigationController ?? NavigationHandler.shared().navigationController else { return nil }
return NavigationOperation(with: .push(viewController: viewController, navigationController: navigationController, animated: shouldAnimate), tryToReplace: true, delegate: delegateObject?.presentationDelegate)
}
}
/// Gets the navigation operation based on the loadObject.
@MainActor
func getNavigationOperation(with viewController: UIViewController, loadObject: MVMCoreLoadObject?) -> NavigationOperation? {
// Lets the server determine the presentation style if not explicitely set by developer.
if loadObject?.requestParameters?.loadStyle == .default,
let presentationStyle = loadObject?.pageJSON?.optionalStringForKey(KeyPresentationStyle) {
// Let's the response override if needed.
loadObject?.requestParameters?.setMFLoadStyleBasedOnPresentationStyle(presentationStyle)
}
// Check if we need to load on another control
var viewController = viewController
if let coreViewController = viewController as? UIViewController & MVMCoreViewControllerProtocol,
let viewControllerToLoad = MVMCoreObject.sharedInstance()?.globalLoadDelegate?.getViewManager?(with: coreViewController, loadObject: loadObject) {
viewController = viewControllerToLoad
}
guard let requestParameters = loadObject?.requestParameters else {
// Push
guard let navigationController = NavigationHandler.shared().navigationController else { return nil }
return NavigationOperation(with: .push(viewController: viewController, navigationController: navigationController))
}
return NavigationHandler.shared().getNavigationOperation(with: requestParameters, viewController: viewController, delegateObject: loadObject?.delegateObject)
}
}

View File

@ -10,7 +10,6 @@
#import <UIKit/UIKit.h>
#import <MVMCore/MVMCoreViewControllerProtocol.h>
#import <MVMCore/MVMCoreLoadObject.h>
#import <MVMCore/MVMCorePresentationDelegateProtocol.h>
@interface MVMCoreActionUtility : NSObject
@ -20,9 +19,6 @@
// Links away to safari or another app. Returns if successful.
+ (BOOL)linkAway:(nullable NSString *)safariURLString appURLString:(nullable NSString *)appURLString;
// Can call to display a view controller based on the load object in the same way the architecture does it. Will check the presentation style of the page, action, and request. Will check if needs a view manager.
+ (void)displayViewController:(nonnull UIViewController <MVMCoreViewControllerProtocol> *)viewController forLoadObject:(nullable MVMCoreLoadObject *)loadObject presentationDelegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock;
// returns if the class is not the same or a subclass of the other class. Can pass throw an exception as well
+ (BOOL)classIsInstanceTypeOfClass:(nonnull Class)theClass otherClass:(nonnull Class)otherClass throwException:(BOOL)throwException;

View File

@ -104,32 +104,6 @@
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:completion];
}
+ (void)displayViewController:(nonnull UIViewController <MVMCoreViewControllerProtocol> *)viewController forLoadObject:(nullable MVMCoreLoadObject *)loadObject presentationDelegate:(nullable NSObject<MVMCorePresentationDelegateProtocol>*)delegate completionHandler:(nullable void (^)(void))completionBlock {
// Lets the server determine the presentation style if not explicitely set by developer.
if (loadObject.requestParameters.loadStyle == MFLoadStyleDefault) {
// Sets it first based on the action map.
NSString *presentationStyle = [loadObject.requestParameters.actionMap stringForKey:KeyPresentationStyle];
[loadObject.requestParameters setMFLoadStyleBasedOnPresentationStyle:presentationStyle];
// Let's the response override if needed.
presentationStyle = [loadObject.pageJSON stringForKey:KeyPresentationStyle];
[loadObject.requestParameters setMFLoadStyleBasedOnPresentationStyle:presentationStyle];
}
// Check if we need to load on another control
__block UIViewController *viewControllerToLoad = nil;
if ([[MVMCoreObject sharedInstance].globalLoadDelegate respondsToSelector:@selector(getViewManagerWithViewController:loadObject:)]) {
[MVMCoreDispatchUtility performSyncBlockOnMainThread:^{
viewControllerToLoad = [[MVMCoreObject sharedInstance].globalLoadDelegate getViewManagerWithViewController:viewController loadObject:loadObject];
}];
}
// Navigates
[[MVMCoreNavigationHandler sharedNavigationHandler] navigateWithLoadObject:loadObject viewController:(viewControllerToLoad ?: viewController) delegate:delegate completionHandler:completionBlock];
}
+ (BOOL)classIsInstanceTypeOfClass:(Class)theClass otherClass:(Class)otherClass throwException:(BOOL)throwException {
if (theClass != otherClass && ![theClass isSubclassOfClass:otherClass]) {
if (throwException) {