Merge branch 'develop' of gitlab.verizon.com:BPHV_MIPS/mvm_core into develop

This commit is contained in:
Suresh, Kamlesh 2020-03-06 17:37:55 -05:00
commit 29afdf10ed
7 changed files with 77 additions and 67 deletions

View File

@ -42,6 +42,7 @@ extern NSString * const URLComponentKeepAlive;
extern NSString * const NotificationResponseLoaded; extern NSString * const NotificationResponseLoaded;
extern NSString * const MVMCoreNotificationGoingToServer; extern NSString * const MVMCoreNotificationGoingToServer;
extern NSString * const MVMCoreNotificationViewControllerChanged;
#pragma mark - Image Cache #pragma mark - Image Cache
extern NSTimeInterval const ImageTimeOut; extern NSTimeInterval const ImageTimeOut;

View File

@ -29,6 +29,7 @@ NSString * const URLComponentKeepAlive = @"isAlive.jsp";
NSString * const NotificationResponseLoaded = @"responseLoaded"; NSString * const NotificationResponseLoaded = @"responseLoaded";
NSString * const MVMCoreNotificationGoingToServer = @"MVMCoreGoServer"; NSString * const MVMCoreNotificationGoingToServer = @"MVMCoreGoServer";
NSString * const MVMCoreNotificationViewControllerChanged = @"MVMCoreNotificationViewControllerChanged";
#pragma mark - Image Cache #pragma mark - Image Cache
NSTimeInterval const ImageTimeOut = 60; NSTimeInterval const ImageTimeOut = 60;

View File

@ -8,10 +8,6 @@
import Foundation import Foundation
public enum ActionCodingKey: String, CodingKey {
case actionType
}
public protocol ActionModelProtocol: ModelProtocol { public protocol ActionModelProtocol: ModelProtocol {
var actionType: String? { get set } var actionType: String? { get set }

View File

@ -9,7 +9,6 @@
import Foundation import Foundation
public struct ModelRegistry { public struct ModelRegistry {
public enum Error: Swift.Error { public enum Error: Swift.Error {
@ -45,24 +44,21 @@ public struct ModelRegistry {
} }
private static func getCategory<T>(for type: T.Type) -> Category? { private static func getCategory<T>(for type: T.Type) -> Category? {
return categories["\(T.self)"] // Temporary code till we find a better solution.
//if this is a protocol composotion, loop through each protocol for a category lookup
let protocols = String(describing: T.self).components(separatedBy: "&").compactMap{$0.trimmingCharacters(in: .whitespaces)}
return protocols.compactMap({ (p) -> Category? in
guard let c = categories[p] else {
return nil
}
return c
}).first
} }
public static func getType<T>(for name: String, with type: T.Type) -> ModelProtocol.Type? { public static func getType<T>(for name: String, with type: T.Type) -> ModelProtocol.Type? {
return getCategory(for: type)?.instanceTypes[name] return getCategory(for: type)?.instanceTypes[name]
} }
private static func getCategory(for typeString: String) -> Category? {
for (_, value) in categories where value.codingKey == typeString {
return value
}
return nil
}
public static func getType(for name: String, with typeString: String) -> ModelProtocol.Type? {
return getCategory(for: typeString)?.instanceTypes[name]
}
public static func getCodingKey<T>(for type: T.Type) throws -> AnyCodingKey { public static func getCodingKey<T>(for type: T.Type) throws -> AnyCodingKey {
guard let category = getCategory(for: type) else { guard let category = getCategory(for: type) else {
throw ModelRegistry.Error.decoderOther(message: "decodeModelsIfPresent only works for objects implementing the ModelProtocol protocol") throw ModelRegistry.Error.decoderOther(message: "decodeModelsIfPresent only works for objects implementing the ModelProtocol protocol")
@ -77,32 +73,46 @@ extension KeyedDecodingContainer where Key: CodingKey {
// MARK: - Decode // MARK: - Decode
/// Decodes to a registered model based on the identifier /// Decodes to a registered model based on the identifier
public func decodeModel<M, TypeKey: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: TypeKey) throws -> M { public func decodeModel<T>(codingKey: KeyedDecodingContainer<K>.Key) throws -> T {
guard let model: T = try decodeModelIfPresent(codingKey: codingKey) else {
guard let model: ModelProtocol = try decodeModelIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorObjectNotPresent: \(codingKey)") MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorObjectNotPresent: \(codingKey)")
throw ModelRegistry.Error.decoderErrorObjectNotPresent throw ModelRegistry.Error.decoderErrorObjectNotPresent
} }
return model
if let model = model as? M { }
return model
} else { /// Decodes an array of registered model based on the identifiers.
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderError: \(codingKey)") public func decodeModels<T>(codingKey: KeyedDecodingContainer<K>.Key) throws -> [T] {
throw ModelRegistry.Error.decoderError guard let model: [T] = try decodeModelsIfPresent(codingKey: codingKey) else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorObjectNotPresent: \(codingKey)")
throw ModelRegistry.Error.decoderErrorObjectNotPresent
} }
return model
}
/// Decodes an array with arrays of models based on the identifiers.
public func decodeModels2D<T>(codingKey: KeyedDecodingContainer<K>.Key) throws -> [[T]] {
guard let models: [[T]] = try decodeModels2DIfPresent(codingKey: codingKey) else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorObjectNotPresent: \(codingKey)")
throw ModelRegistry.Error.decoderErrorObjectNotPresent
}
return models
} }
// MARK: - DecodeIfPresent // MARK: - DecodeIfPresent
/// Decodes to a registered model based on the identifier, optional. /// Decodes to a registered model based on the identifier, optional.
public func decodeModelIfPresent<M, TypeKey: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: TypeKey) throws -> M? { public func decodeModelIfPresent<T>(codingKey: KeyedDecodingContainer<K>.Key) throws -> T? {
//get the identifier string //create coding key
guard contains(codingKey), let typeCodingKey = try ModelRegistry.getCodingKey(for: T.self)
let container = try? nestedContainer(keyedBy: TypeKey.self, forKey: codingKey),
let identifier = try? container.decodeIfPresent(String.self, forKey: typeCodingKey)
else { return nil }
guard let type = ModelRegistry.getType(for: identifier, with: typeCodingKey.stringValue) else { //get the container that holds the identifier value
guard contains(codingKey),
let container = try? self.nestedContainer(keyedBy: AnyCodingKey.self, forKey: codingKey),
let identifier = try container.decodeIfPresent(String.self, forKey: typeCodingKey) else { return nil }
//get the type from the identifier value in the Registry
guard let type = ModelRegistry.getType(for: identifier, with: T.self) else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelProtocol not mapped: \(identifier)") MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelProtocol not mapped: \(identifier)")
throw ModelRegistry.Error.decoderErrorModelNotMapped throw ModelRegistry.Error.decoderErrorModelNotMapped
} }
@ -110,7 +120,7 @@ extension KeyedDecodingContainer where Key: CodingKey {
//decode the type using the decoder //decode the type using the decoder
let model = try type.decode(keyedContainer: self, codingKey: codingKey) let model = try type.decode(keyedContainer: self, codingKey: codingKey)
if let model = model as? M { if let model = model as? T {
return model return model
} else { } else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderError: \(codingKey)") MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderError: \(codingKey)")
@ -119,39 +129,21 @@ extension KeyedDecodingContainer where Key: CodingKey {
} }
/// Decodes an array of registered model based on the identifiers, optional. /// Decodes an array of registered model based on the identifiers, optional.
public func decodeModelsIfPresent<TypeKey: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: TypeKey) throws -> [ModelProtocol]? { public func decodeModelsIfPresent<T>(codingKey: KeyedDecodingContainer<K>.Key) throws -> [T]? {
guard contains(codingKey), guard contains(codingKey),
var container = try? self.nestedUnkeyedContainer(forKey: codingKey) var container = try? self.nestedUnkeyedContainer(forKey: codingKey)
else { return nil } else { return nil }
return try container.decodeModelsIfPresent(typeCodingKey: typeCodingKey) return try container.decodeModelsIfPresent()
}
/// Decodes an array of registered model based on the identifiers.
public func decodeModels<TypeKey: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: TypeKey) throws -> [ModelProtocol] {
guard let models: [ModelProtocol] = try decodeModelsIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorObjectNotPresent: \(codingKey)")
throw ModelRegistry.Error.decoderErrorObjectNotPresent
}
return models
} }
/// Decodes an array with arrays of models based on the identifiers, optional. /// Decodes an array with arrays of models based on the identifiers, optional.
public func decodeModels2DIfPresent<TypeKey: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: TypeKey) throws -> [[ModelProtocol]]? { public func decodeModels2DIfPresent<T>(codingKey: KeyedDecodingContainer<K>.Key) throws -> [[T]]? {
guard contains(codingKey), guard contains(codingKey),
var container = try? nestedUnkeyedContainer(forKey: codingKey) var container = try? nestedUnkeyedContainer(forKey: codingKey)
else { return nil } else { return nil }
return try container.decodeModels2DIfPresent(typeCodingKey: typeCodingKey) return try container.decodeModels2DIfPresent()
}
/// Decodes an array with arrays of models based on the identifiers.
public func decodeModels2D<TypeKey: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: TypeKey) throws -> [[ModelProtocol]] {
guard let models: [[ModelProtocol]] = try decodeModels2DIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorObjectNotPresent: \(codingKey)")
throw ModelRegistry.Error.decoderErrorObjectNotPresent
}
return models
} }
} }
@ -205,36 +197,42 @@ public extension KeyedEncodingContainer where Key: CodingKey {
public extension UnkeyedDecodingContainer { public extension UnkeyedDecodingContainer {
/// Decodes the container into a list of Models. /// Decodes the container into a list of Models.
mutating func decodeModelsIfPresent<TypeKey: CodingKey>(typeCodingKey: TypeKey) throws -> [ModelProtocol]? { mutating func decodeModelsIfPresent<T>() throws -> [T]? {
let typeCodingKey = try ModelRegistry.getCodingKey(for: T.self)
var models = [ModelProtocol]() var models = [T]()
var containerCopy = self var containerCopy = self
// Iterate and decode each.
while !containerCopy.isAtEnd { while !containerCopy.isAtEnd {
let nestedContainer = try containerCopy.nestedContainer(keyedBy: TypeKey.self) let nestedContainer = try containerCopy.nestedContainer(keyedBy: AnyCodingKey.self)
if let identifier = try nestedContainer.decodeIfPresent(String.self, forKey: typeCodingKey) { if let identifier = try nestedContainer.decodeIfPresent(String.self, forKey: typeCodingKey) {
guard let type = ModelRegistry.getType(for: identifier, with: typeCodingKey.stringValue) else { guard let type = ModelRegistry.getType(for: identifier, with: T.self) else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorModelNotMapped: \(identifier)") MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorModelNotMapped: \(identifier)")
throw ModelRegistry.Error.decoderErrorModelNotMapped throw ModelRegistry.Error.decoderErrorModelNotMapped
} }
// Now get the decoder to use for the type // Now get the decoder to use for the type
let decoder = try self.superDecoder() let decoder = try self.superDecoder()
let model = try type.init(from: decoder) if let model = try type.init(from: decoder) as? T {
models.append(model) models.append(model)
} else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderError: \(typeCodingKey)")
throw ModelRegistry.Error.decoderError
}
} }
} }
return models return models
} }
/// Convenience function for decoding the container into a list of lists of Models. /// Convenience function for decoding the container into a list of lists of Models.
mutating func decodeModels2DIfPresent<TypeKey: CodingKey>(typeCodingKey: TypeKey) throws -> [[ModelProtocol]]? { mutating func decodeModels2DIfPresent<T>() throws -> [[T]]? {
let typeCodingKey = try ModelRegistry.getCodingKey(for: T.self)
var modelLists = [[ModelProtocol]]() var modelLists = [[T]]()
var containerCopy = self var containerCopy = self
// Iterate and decode each.
while !containerCopy.isAtEnd { while !containerCopy.isAtEnd {
var arraycontainerCopy = try containerCopy.nestedUnkeyedContainer() var arraycontainerCopy = try containerCopy.nestedUnkeyedContainer()
guard let models = try arraycontainerCopy.decodeModelsIfPresent(typeCodingKey: typeCodingKey) else { guard let models: [T] = try arraycontainerCopy.decodeModelsIfPresent() else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorModelNotMapped: \(typeCodingKey)") MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ModelRegistry Error decoderErrorModelNotMapped: \(typeCodingKey)")
throw ModelRegistry.Error.decoderErrorModelNotMapped throw ModelRegistry.Error.decoderErrorModelNotMapped
} }

View File

@ -7,6 +7,7 @@
// //
#import "MVMCoreDismissViewControllerOperation.h" #import "MVMCoreDismissViewControllerOperation.h"
#import "MVMCoreConstants.h"
typedef NS_ENUM(NSInteger, DismissType) { typedef NS_ENUM(NSInteger, DismissType) {
DismissTypeTop = 0, DismissTypeTop = 0,
@ -77,6 +78,10 @@ typedef NS_ENUM(NSInteger, DismissType) {
if (viewController.presentedViewController || viewController.presentingViewController) { if (viewController.presentedViewController || viewController.presentingViewController) {
[viewController dismissViewControllerAnimated:self.animate completion:^{ [viewController dismissViewControllerAnimated:self.animate completion:^{
[self markAsFinished]; [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 { } else {
[self markAsFinished]; [self markAsFinished];

View File

@ -242,6 +242,10 @@
[self.delegate navigationController:navigationController displayedViewController:viewController]; [self.delegate navigationController:navigationController displayedViewController:viewController];
} }
[self markAsFinished]; [self markAsFinished];
// 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 { - (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {

View File

@ -10,6 +10,7 @@
#import "MVMCoreAlertController.h" #import "MVMCoreAlertController.h"
#import "MVMCorePresentAnimationOperation.h" #import "MVMCorePresentAnimationOperation.h"
#import "MVMCoreDispatchUtility.h" #import "MVMCoreDispatchUtility.h"
#import "MVMCoreConstants.h"
@interface MVMCorePresentViewControllerOperation () @interface MVMCorePresentViewControllerOperation ()
@ -74,6 +75,10 @@ static void * XXContext = &XXContext;
animationOperation.delegate = self.delegate; animationOperation.delegate = self.delegate;
[animationOperation setCompletionBlock:^{ [animationOperation setCompletionBlock:^{
[self markAsFinished]; [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]; [[NSOperationQueue mainQueue] addOperation:animationOperation];
} }