Compare commits

..

No commits in common. "8858f89a5ce8bdd8870e29ca626012e04eee83a8" and "875abb11e9a69fb6030b1b71ede587f7d9faf1a1" have entirely different histories.

11 changed files with 36 additions and 239 deletions

View File

@ -157,9 +157,6 @@
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 */
@ -307,9 +304,6 @@
D2DEDCBA23C65BC300C44CC4 /* Percent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Percent.swift; sourceTree = "<group>"; };
D2E1FAD82260C3E400AEFD8C /* DelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelegateObject.swift; sourceTree = "<group>"; };
EA3B264B25FC0B7600008074 /* ModelHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelHandlerProtocol.swift; sourceTree = "<group>"; };
EA48AAE327D16DE400678D5C /* AnyHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyHandler.swift; sourceTree = "<group>"; };
EA48AAE527D16DF500678D5C /* ModelHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelHandler.swift; sourceTree = "<group>"; };
EA48AAE727D16E2900678D5C /* HandlerRequestProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandlerRequestProtocol.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -621,9 +615,6 @@
AFBB96B61FBA3CEC0008D868 /* MVMCoreActionHandler.h */,
AFBB96B71FBA3CEC0008D868 /* MVMCoreActionHandler.m */,
D27073CC25BB4CEF001C7246 /* MVMCoreActionHandler+Extension.swift */,
EA48AAE327D16DE400678D5C /* AnyHandler.swift */,
EA48AAE527D16DF500678D5C /* ModelHandler.swift */,
EA48AAE727D16E2900678D5C /* HandlerRequestProtocol.swift */,
);
path = ActionHandling;
sourceTree = "<group>";
@ -859,7 +850,6 @@
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 */,
@ -877,11 +867,9 @@
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 */,

View File

@ -1,36 +0,0 @@
//
// 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<Response, Error: Swift.Error>: HandlerRequestProtocol {
//Performable method
private let performObject: () -> Void
//HandlerRequestProtocol method
private let performHandlerObject: (@escaping (Result<Response, Error>) -> Void) -> Void
//Ensures the Request and Handler Response and Error Type match
public init<Request: HandlerRequestProtocol>(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)
}
}

View File

@ -1,23 +0,0 @@
//
// 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<Response, Error>) -> Void
//Method to be implemented by Request
func perform(then handler: @escaping Handler)
}

View File

@ -7,19 +7,10 @@
//
import Foundation
import UIKit
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 protocol MVMCoreActionHandlerProtocol: ModelHandlerProtocol {
init()
func handleAction(_ model: ActionModelProtocol, additionalData: [AnyHashable : Any]?, delegateObject: DelegateObject?)
}
public extension MVMCoreActionHandler {
@ -49,7 +40,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? MVMCoreHandlerProtocol.Type
let actionHandlerType = try? ModelRegistry.getHandlerType(for: actionModelType) as? MVMCoreActionHandlerProtocol.Type
else { return false }
do {
@ -58,12 +49,11 @@ public extension MVMCoreActionHandler {
throw ModelRegistry.Error.decoderOther(message: "Could not decode to ActionModelProtocol")
}
//create the handler since we know it can initialize
let actionHandler = try? actionHandlerType.init(baseModel: actionModel,
additionalData: additionalData,
delegateObject: delegateObject)
actionHandler?.perform()
let actionHandler = actionHandlerType.init()
//call the handleAction of the handler
actionHandler.handleAction(actionModel, additionalData: additionalData, delegateObject: delegateObject)
} catch {
//log the error

View File

@ -1,61 +0,0 @@
//
// 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<Model: ModelProtocol, Response>: 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()
}
}

View File

@ -9,6 +9,13 @@
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
typedef NS_ENUM(NSInteger, MVMAppContext) {
MVMAppContextNone = 0,
MVMAppContextMF,
MVMAppContextMFPrepay,
MVMAppContextContentTransfer
};
typedef NS_ENUM(NSInteger, NavigationType) {
NavigationTypePush = 0,
NavigationTypeSet,

View File

@ -25,15 +25,11 @@ extension Encodable {
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? JSONDictionary }
}
public func toJSONAny() throws -> [String: Any] {
let data = try self.encode()
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
guard let jsonAny = json as? [String: Any] else {
throw JSONError.error(message: "JSON Dictionary not found")
}
return jsonAny
public func toJSONAny() -> [String: Any]? {
guard let data = try? self.encode() else { return nil }
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] }
}
public func toJSONString() -> String? {
guard let json = self.toJSON(),
let data = try? JSONSerialization.data(withJSONObject: json, options: .prettyPrinted),

View File

@ -8,54 +8,11 @@
import Foundation
public typealias JSONArray = [AnyHashable]
public typealias JSONArray = [[String: Any]]
public typealias JSONDictionary = [String: AnyHashable]
public enum JSONError: Error {
case pathNotFound
case data(path: String)
case other(error: Error)
case error(message: String)
}
extension JSONDictionary {
public func toJSONString(options: JSONSerialization.WritingOptions = []) throws -> String {
let data = try JSONSerialization.data(withJSONObject: self, options: options)
guard let string = String(data: data, encoding: .utf8) else {
throw JSONError.error(message: "Failed to convert data to string")
}
return string
}
public func toUrlQueryItems() throws -> [URLQueryItem] {
var queryItems: [URLQueryItem] = []
for (key, value) in self {
var valueString: String
if let value = value as? JSONDictionary {
valueString = try value.toJSONString()
} else if let value = value as? JSONArray {
valueString = try value.toJSONString()
} else {
guard let baseValueString = String(describing: value.base).removingPercentEncoding else {
throw JSONError.error(message: "query item failed: \(key) value \(value.base)")
}
valueString = baseValueString
}
let queryItem = URLQueryItem(name: key, value: valueString)
queryItems.append(queryItem)
}
return queryItems
}
}
extension JSONArray {
public func toJSONString(options: JSONSerialization.WritingOptions = []) throws -> String {
let data = try JSONSerialization.data(withJSONObject: self, options: options)
guard let string = String(data: data, encoding: .utf8) else {
throw JSONError.error(message: "Failed to convert data to string")
}
return string
}
}

View File

@ -13,7 +13,6 @@ public typealias JSONValueDictionary = [String: JSONValue]
public enum JSONValueError: Error {
case encode
case TypeMismatch
}
extension Optional {
@ -70,36 +69,25 @@ public enum JSONValue: Codable, Equatable {
}
}
public var base: Any {
public var base: Any? {
switch self {
case .string(let string): return string
case .int(let int): return int
case .double(let double): return double
case .bool(let bool): return bool
case .object(let object): return try! object.toJSONAny()
case .array(let array): return try! ["array": array].toJSONAny()["array"]!
case .null: return NSNull()
case .object(let object): return object.toJSONAny()
case .array(let array): return ["array": array].toJSONAny()?["array"]
case .null: return nil
}
}
public func value<T>() throws -> T {
guard let base = self.base as? T else {
throw JSONValueError.TypeMismatch
}
return base
}
private func value<T>(type: T.Type) throws -> T {
let base: T = try value()
return base
}
public func toString() throws -> String { try value(type: String.self) }
public func toDouble() throws -> Double { try value(type: Double.self) }
public func toInt() throws -> Int { try value(type: Int.self) }
public func toBool() throws -> Bool { try value(type: Bool.self) }
public func toArray<T>(of type: T.Type) throws -> [T]{ try value(type: [T].self) }
public func toObject<T>(of type: T.Type) throws -> T { try value(type: T.self) }
public func value<T>() -> T? { self.base as? T }
public func toString() -> String? { self.base as? String }
public func toDouble() -> Double? { self.base as? Double }
public func toInt() -> Int? { self.base as? Int }
public func toBool() -> Bool? { self.base as? Bool }
public func toArray<T>(of type: T.Type) -> [T]?{ self.base as? [T] }
public func toObject<T>(of type: T.Type) -> T? { self.base as? T }
}
@ -152,13 +140,6 @@ extension Dictionary where Key == String, Value == Any {
}
}
extension Dictionary where Key == String, Value == AnyHashable {
public func toJSONValue() throws -> [String: JSONValue] {
let data = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
return try JSONDecoder().decode([String:JSONValue].self, from: data)
}
}
extension Dictionary where Key == String, Value == JSONValue {
public func toJSONObject() throws -> JSONDictionary {
let encoded = try JSONEncoder().encode(self)

View File

@ -24,10 +24,10 @@ public struct ModelRegistry {
}
public struct Category {
public var name: String
public var codingKey: String
public var instanceTypes: [String: ModelProtocol.Type] = [:]
public var handlerTypes: [String: ModelHandlerProtocol.Type] = [:]
var name: String
var codingKey: String
var instanceTypes: [String: ModelProtocol.Type] = [:]
var handlerTypes: [String: ModelHandlerProtocol.Type] = [:]
}
public static var categories: [String: Category] = [:]

View File

@ -91,9 +91,7 @@
NSString *type = [errorInfo string:KeyType];
if (![ValueTypeSuccess isEqualToString:type]) {
NSString *title = [errorInfo string:KeyErrorHeading] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
NSString *message = [errorInfo string:KeyUserMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
MVMCoreErrorObject *error = [[MVMCoreErrorObject alloc] initWithTitle:title message:message messageToLog:[errorInfo string:KeyMessage] code:errorCode domain:ErrorDomainServer location:location];
MVMCoreErrorObject *error = [[MVMCoreErrorObject alloc] initWithTitle:[errorInfo stringForKey:KeyErrorHeading] message:[errorInfo stringForKey:KeyUserMessage] messageToLog:[errorInfo stringForKey:KeyMessage] code:errorCode domain:ErrorDomainServer location:location];
if ([ValueTypeErrorScreen isEqualToString:type]) {
// If this is a server error screen, there should be no additional alerts... It will be handled by the load handler.