From f61e67df6bed34f2569eded3b151eca688e393c8 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 3 Mar 2022 16:04:19 -0600 Subject: [PATCH] create new ModelHandler protocol/classes Signed-off-by: Matt Bruce # Conflicts: # MVMCore/MVMCore.xcodeproj/project.pbxproj Signed-off-by: Matt Bruce --- MVMCore/MVMCore.xcodeproj/project.pbxproj | 12 ++++ .../MVMCore/ActionHandling/AnyHandler.swift | 36 +++++++++++ .../HandlerRequestProtocol.swift | 23 +++++++ .../MVMCoreActionHandler+Extension.swift | 26 +++++--- .../MVMCore/ActionHandling/ModelHandler.swift | 61 +++++++++++++++++++ 5 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 MVMCore/MVMCore/ActionHandling/AnyHandler.swift create mode 100644 MVMCore/MVMCore/ActionHandling/HandlerRequestProtocol.swift create mode 100644 MVMCore/MVMCore/ActionHandling/ModelHandler.swift diff --git a/MVMCore/MVMCore.xcodeproj/project.pbxproj b/MVMCore/MVMCore.xcodeproj/project.pbxproj index edfc67b..7ff0875 100644 --- a/MVMCore/MVMCore.xcodeproj/project.pbxproj +++ b/MVMCore/MVMCore.xcodeproj/project.pbxproj @@ -159,6 +159,9 @@ D2DEDCBB23C65BC300C44CC4 /* Percent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2DEDCBA23C65BC300C44CC4 /* Percent.swift */; }; D2E1FAD92260C3E400AEFD8C /* DelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAD82260C3E400AEFD8C /* DelegateObject.swift */; }; EA3B264C25FC0B7600008074 /* ModelHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3B264B25FC0B7600008074 /* ModelHandlerProtocol.swift */; }; + EA48AAE427D16DE400678D5C /* AnyHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA48AAE327D16DE400678D5C /* AnyHandler.swift */; }; + EA48AAE627D16DF500678D5C /* ModelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA48AAE527D16DF500678D5C /* ModelHandler.swift */; }; + EA48AAE827D16E2900678D5C /* HandlerRequestProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA48AAE727D16E2900678D5C /* HandlerRequestProtocol.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -308,6 +311,9 @@ D2DEDCBA23C65BC300C44CC4 /* Percent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Percent.swift; sourceTree = ""; }; D2E1FAD82260C3E400AEFD8C /* DelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelegateObject.swift; sourceTree = ""; }; EA3B264B25FC0B7600008074 /* ModelHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelHandlerProtocol.swift; sourceTree = ""; }; + EA48AAE327D16DE400678D5C /* AnyHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyHandler.swift; sourceTree = ""; }; + EA48AAE527D16DF500678D5C /* ModelHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelHandler.swift; sourceTree = ""; }; + EA48AAE727D16E2900678D5C /* HandlerRequestProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandlerRequestProtocol.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -621,6 +627,9 @@ AF130B8D2788DF6E00C6C03C /* OpenURLOptionsModel.swift */, 01F2A03823A812DD00D954D8 /* ActionOpenUrlModel.swift */, AF8D13382774EA1D008AF4A9 /* ActionOpenUrlHandler.swift */, + EA48AAE327D16DE400678D5C /* AnyHandler.swift */, + EA48AAE527D16DF500678D5C /* ModelHandler.swift */, + EA48AAE727D16E2900678D5C /* HandlerRequestProtocol.swift */, ); path = ActionHandling; sourceTree = ""; @@ -858,6 +867,7 @@ 01F2A03623A80A7300D954D8 /* ActionModelProtocol.swift in Sources */, AFBB96991FBA3A9A0008D868 /* MVMCoreAlertController.m in Sources */, 881D26941FCC9D180079C521 /* MVMCoreOperation.m in Sources */, + EA48AAE627D16DF500678D5C /* ModelHandler.swift in Sources */, AFED77A41FCCA29400BAE689 /* MVMCoreViewControllerMappingObject.m in Sources */, 01C851CF23CF7B260021F976 /* JSONMap.swift in Sources */, 01F2A04C23A82B1B00D954D8 /* ActionCallModel.swift in Sources */, @@ -875,9 +885,11 @@ 881D26931FCC9D180079C521 /* MVMCoreErrorObject.m in Sources */, 94C014D124211869005811A9 /* ActionRestartModel.swift in Sources */, D288D5F526C6EFE000A5C365 /* MVMCoreLoggingHandler+Extension.swift in Sources */, + EA48AAE427D16DE400678D5C /* AnyHandler.swift in Sources */, 946EE1B0237B5EF70036751F /* JSONHelper.swift in Sources */, 30349BF21FCCA78A00546A1E /* MVMCoreSessionTimeHandler.m in Sources */, D2DEDCB923C6400600C44CC4 /* UnitInterval.swift in Sources */, + EA48AAE827D16E2900678D5C /* HandlerRequestProtocol.swift in Sources */, 94C014D3242119E6005811A9 /* ActionPreviousSubmitModel.swift in Sources */, 8876D5E91FB50AB000EB2E3D /* NSArray+MFConvenience.m in Sources */, D27073B725BB45C4001C7246 /* ActionActionsModel.swift in Sources */, diff --git a/MVMCore/MVMCore/ActionHandling/AnyHandler.swift b/MVMCore/MVMCore/ActionHandling/AnyHandler.swift new file mode 100644 index 0000000..2cf6f38 --- /dev/null +++ b/MVMCore/MVMCore/ActionHandling/AnyHandler.swift @@ -0,0 +1,36 @@ +// +// AnyHandler.swift +// MVMCore +// +// Created by Matt Bruce on 3/3/22. +// Copyright © 2022 myverizon. All rights reserved. +// + +import Foundation + + +/// Type Erased class for HandlerRequestProtocol +public class AnyHandler: HandlerRequestProtocol { + + //Performable method + private let performObject: () -> Void + //HandlerRequestProtocol method + private let performHandlerObject: (@escaping (Result) -> Void) -> Void + + //Ensures the Request and Handler Response and Error Type match + public init(wrappedRequest: Request) where Request.Response == Response, Request.Error == Error{ + self.performObject = wrappedRequest.perform + self.performHandlerObject = wrappedRequest.perform + } + + /// Implementation to call wrapped method + public func perform() { + self.performObject() + } + + /// Implementation that calls the wrapped method + /// - Parameter handler: <#handler description#> + public func perform(then handler: @escaping Handler) { + self.performHandlerObject(handler) + } +} diff --git a/MVMCore/MVMCore/ActionHandling/HandlerRequestProtocol.swift b/MVMCore/MVMCore/ActionHandling/HandlerRequestProtocol.swift new file mode 100644 index 0000000..9d3d2c1 --- /dev/null +++ b/MVMCore/MVMCore/ActionHandling/HandlerRequestProtocol.swift @@ -0,0 +1,23 @@ +// +// HandlerRequestProtocol.swift +// MVMCore +// +// Created by Matt Bruce on 3/3/22. +// Copyright © 2022 myverizon. All rights reserved. +// + +import Foundation + +//Protocol following Request to Response/Error Contract +public protocol HandlerRequestProtocol: Performable { + //Type returned in Success + associatedtype Response + //Type returned in Error + associatedtype Error: Swift.Error + + //Handler alias + typealias Handler = (Result) -> Void + + //Method to be implemented by Request + func perform(then handler: @escaping Handler) +} diff --git a/MVMCore/MVMCore/ActionHandling/MVMCoreActionHandler+Extension.swift b/MVMCore/MVMCore/ActionHandling/MVMCoreActionHandler+Extension.swift index 8b66d82..412045d 100644 --- a/MVMCore/MVMCore/ActionHandling/MVMCoreActionHandler+Extension.swift +++ b/MVMCore/MVMCore/ActionHandling/MVMCoreActionHandler+Extension.swift @@ -7,10 +7,19 @@ // import Foundation +import UIKit -public protocol MVMCoreActionHandlerProtocol: ModelHandlerProtocol { - init() - func handleAction(_ model: ActionModelProtocol, additionalData: [AnyHashable : Any]?, delegateObject: DelegateObject?) + +public protocol Performable{ + func perform() +} + +//Base Signature for a Handler - Model relationship +public protocol MVMCoreHandlerProtocol: ModelHandlerProtocol, Performable { + var baseModel: ModelProtocol { get set } + var additionalData: [AnyHashable: Any]? { get set } + var delegateObject: DelegateObject? { get set } + init (baseModel: ModelProtocol, additionalData: [AnyHashable : Any]?, delegateObject: DelegateObject?) throws } public extension MVMCoreActionHandler { @@ -40,7 +49,7 @@ public extension MVMCoreActionHandler { //esnure the actionModelType let actionModelType = ModelRegistry.getType(for: actionType, with: ActionModelProtocol.self), //ensure there is handlerType for the action of MVMCoreActionHandlerProtocol - let actionHandlerType = try? ModelRegistry.getHandlerType(for: actionModelType) as? MVMCoreActionHandlerProtocol.Type + let actionHandlerType = try? ModelRegistry.getHandlerType(for: actionModelType) as? MVMCoreHandlerProtocol.Type else { return false } do { @@ -49,11 +58,12 @@ public extension MVMCoreActionHandler { throw ModelRegistry.Error.decoderOther(message: "Could not decode to ActionModelProtocol") } - //create the handler since we know it can initialize - let actionHandler = actionHandlerType.init() - //call the handleAction of the handler - actionHandler.handleAction(actionModel, additionalData: additionalData, delegateObject: delegateObject) + //create the handler since we know it can initialize + let actionHandler = try? actionHandlerType.init(baseModel: actionModel, + additionalData: additionalData, + delegateObject: delegateObject) + actionHandler?.perform() } catch { //log the error diff --git a/MVMCore/MVMCore/ActionHandling/ModelHandler.swift b/MVMCore/MVMCore/ActionHandling/ModelHandler.swift new file mode 100644 index 0000000..bbcad4f --- /dev/null +++ b/MVMCore/MVMCore/ActionHandling/ModelHandler.swift @@ -0,0 +1,61 @@ +// +// ModelHandler.swift +// MVMCore +// +// Created by Matt Bruce on 3/3/22. +// Copyright © 2022 myverizon. All rights reserved. +// + +import Foundation + + +/// Abstract Handler class for any type of ModelProtocol +open class ModelHandler: NSObject, MVMCoreHandlerProtocol, HandlerRequestProtocol { + //Success Type from the Result + public typealias Response = Response + //Error Type from the Result + public typealias Error = Swift.Error + + //base properties + + //baseModel that is tied to this handler + public var baseModel: ModelProtocol + public var additionalData: [AnyHashable: Any]? + public weak var delegateObject: DelegateObject? + + //Need to be a property so that you can access + //the handler outside of the "perform(then: handler) + public var handler: Handler! + + //typed ModelProtocl this handler is expecting + public var model: Model + + //initilization + required public init (baseModel: ModelProtocol, + additionalData: [AnyHashable : Any]?, + delegateObject: DelegateObject?) throws { + //set the properties + self.baseModel = baseModel + self.additionalData = additionalData + self.delegateObject = delegateObject + + //ensure the baseModel is of the Model type you are expecting + guard let castedBridgeModel = baseModel as? Model else { + throw ModelRegistry.Error.other(message: "Models Don't match") + } + //set the model + self.model = castedBridgeModel + super.init() + } + + //only called in a Void scenario + open func perform() { + fatalError("must override perform") + } + + //only called when you want a completion handler. + open func perform(then handler: @escaping Handler) { + self.handler = handler + self.perform() + } +}