Compare commits

..

No commits in common. "develop" and "bugfix/modelRegistryError" have entirely different histories.

42 changed files with 62 additions and 575 deletions

View File

@ -42,7 +42,6 @@
2723337B28BD534D004EAEE0 /* MVMCoreEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2723337A28BD534D004EAEE0 /* MVMCoreEvent.swift */; };
2723337D28BD53C2004EAEE0 /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2723337C28BD53C2004EAEE0 /* Date+Extension.swift */; };
5846ABF42B44BB9000FA6C76 /* Collection+Safe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846ABF32B44BB9000FA6C76 /* Collection+Safe.swift */; };
5878F0B22BDAA63E00ADE23D /* ReadableDecodingErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878F0B12BDAA63E00ADE23D /* ReadableDecodingErrors.swift */; };
6042E8FC2B317B190031644B /* MVMCoreLoggingHandlerHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 6042E8FB2B3094680031644B /* MVMCoreLoggingHandlerHelper.h */; settings = {ATTRIBUTES = (Public, ); }; };
605A9A2A2ABD712F00487E47 /* MVMCoreLoggingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 605A9A292ABD712F00487E47 /* MVMCoreLoggingHandler.swift */; };
6079EDCE2AD97AA5004B7A85 /* MVMCoreLoggingDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6079EDCD2AD97AA5004B7A85 /* MVMCoreLoggingDelegateProtocol.swift */; };
@ -195,7 +194,6 @@
581FABEE2A71D0E6003A8508 /* mvmcore_dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcore_dev.xcconfig; sourceTree = "<group>"; };
5836B8E22A4338DF002553D9 /* mvmcore.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcore.xcconfig; sourceTree = "<group>"; };
5846ABF32B44BB9000FA6C76 /* Collection+Safe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Collection+Safe.swift"; sourceTree = "<group>"; };
5878F0B12BDAA63E00ADE23D /* ReadableDecodingErrors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadableDecodingErrors.swift; sourceTree = "<group>"; };
6042E8FB2B3094680031644B /* MVMCoreLoggingHandlerHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreLoggingHandlerHelper.h; sourceTree = "<group>"; };
605A9A292ABD712F00487E47 /* MVMCoreLoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreLoggingHandler.swift; sourceTree = "<group>"; };
6079EDCD2AD97AA5004B7A85 /* MVMCoreLoggingDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreLoggingDelegateProtocol.swift; sourceTree = "<group>"; };
@ -293,6 +291,7 @@
AFBB96AE1FBA3B590008D868 /* MVMCoreGetterUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreGetterUtility.h; sourceTree = "<group>"; };
AFBB96AF1FBA3B590008D868 /* MVMCoreGetterUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreGetterUtility.m; sourceTree = "<group>"; };
AFBB96B51FBA3CEC0008D868 /* MVMCoreActionDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreActionDelegateProtocol.h; sourceTree = "<group>"; };
AFBB96D21FBA44420008D868 /* VZWAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VZWAuthentication.framework; path = ../../SharedFrameworks/VZWAuthentication.framework; sourceTree = "<group>"; };
AFBB96E91FBA4A260008D868 /* MFHardCodedServerResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFHardCodedServerResponse.h; sourceTree = "<group>"; };
AFBB96EA1FBA4A260008D868 /* MFHardCodedServerResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFHardCodedServerResponse.m; sourceTree = "<group>"; };
AFEA17A6209B6A1C00BC6740 /* MVMCoreBlockOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreBlockOperation.h; sourceTree = "<group>"; };
@ -397,7 +396,6 @@
children = (
AF60A7F1289212CA00919EEB /* MVMError.swift */,
AF60A7F3289212EB00919EEB /* MVMCoreError.swift */,
5878F0B12BDAA63E00ADE23D /* ReadableDecodingErrors.swift */,
881D26911FCC9D180079C521 /* MVMCoreErrorObject.h */,
881D268F1FCC9D180079C521 /* MVMCoreErrorObject.m */,
881D26921FCC9D180079C521 /* MVMCoreOperation.h */,
@ -650,6 +648,7 @@
AF43A6FC1FBE2F2A008E9347 /* Reachability */,
AF43A5C01FBB76D5008E9347 /* CoreGraphics.framework */,
AF43A5BF1FBB76C3008E9347 /* UIKit.framework */,
AFBB96D21FBA44420008D868 /* VZWAuthentication.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -878,7 +877,6 @@
AFA4931E29E5C988001A9663 /* MVMCoreActionUtility+Extension.swift in Sources */,
1DAD0FFE26AAB40000216E83 /* ActionRunJavaScriptModel.swift in Sources */,
946EE1AB237B5C940036751F /* Decoder.swift in Sources */,
5878F0B22BDAA63E00ADE23D /* ReadableDecodingErrors.swift in Sources */,
2723337D28BD53C2004EAEE0 /* Date+Extension.swift in Sources */,
AF70699A287DD02400077CF6 /* ActionContactHandler.swift in Sources */,
AF69D4F3286E9DCE00BC6862 /* ActionActionsHandler.swift in Sources */,
@ -1113,7 +1111,7 @@
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../../SharedFrameworks";
INFOPLIST_FILE = MVMCore/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
MARKETING_VERSION = 3.1;
@ -1140,7 +1138,7 @@
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../../SharedFrameworks";
INFOPLIST_FILE = MVMCore/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
MARKETING_VERSION = 3.1;

View File

@ -64,19 +64,4 @@ public struct ActionActionsModel: ActionModelProtocol {
try container.encodeIfPresent(extraParameters, forKey: .extraParameters)
try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return actions.isEqual(to: model.actions)
&& concurrent == model.concurrent
&& extraParameters == model.extraParameters
&& analyticsData == model.analyticsData
}
}
extension ActionActionsModel: CustomDebugStringConvertible {
public var debugDescription: String {
return "\(Self.self) [\(actions)]"
}
}

View File

@ -25,12 +25,4 @@ public struct ActionBackModel: ActionModelProtocol {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
// Default
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return model.actionType == actionType
&& model.extraParameters == extraParameters
&& model.analyticsData == analyticsData
}
}

View File

@ -28,11 +28,4 @@ public struct ActionCallModel: ActionModelProtocol {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return extraParameters == model.extraParameters
&& analyticsData == model.analyticsData
&& callNumber == model.callNumber
}
}

View File

@ -25,12 +25,4 @@ public struct ActionCancelModel: ActionModelProtocol {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
// Default
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return model.actionType == actionType
&& model.extraParameters == extraParameters
&& model.analyticsData == analyticsData
}
}

View File

@ -42,14 +42,4 @@ public struct ActionContactModel: ActionModelProtocol {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return extraParameters == model.extraParameters
&& analyticsData == model.analyticsData
&& phoneNumber == model.phoneNumber
&& firstName == model.firstName
&& lastName == model.lastName
&& approach == model.approach
}
}

View File

@ -7,7 +7,6 @@
//
public struct ActionNoopModel: ActionModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -25,12 +24,4 @@ public struct ActionNoopModel: ActionModelProtocol {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
// Default
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return model.actionType == actionType
&& model.extraParameters == extraParameters
&& model.analyticsData == analyticsData
}
}

View File

@ -86,7 +86,7 @@ open class ActionOpenPageHandler: MVMCoreJSONActionHandlerProtocol {
let fetchedParameters = await ClientParameterHandler().getClientParameters(
with: parametersToFetch,
requestParameters: requestParameters.parameters as? [String : Any] ?? [:],
actionId: actionUUID,
actionId: MVMCoreActionHandler.getUUID(additionalData: additionalData) ?? "unknown",
showLoadingOverlay: !requestParameters.backgroundRequest) {
requestParameters.add(fetchedParameters)
}

View File

@ -115,31 +115,4 @@ public struct ActionOpenPageModel: ActionModelProtocol, ActionOpenPageProtocol,
try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
try container.encodeIfPresent(fallbackResponse, forKey: .fallbackResponse)
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return pageType == model.pageType
&& baseURL == model.baseURL
&& appContext == model.appContext
&& requestURL == model.requestURL
&& modules == model.modules
&& presentationStyle == model.presentationStyle
&& tabBarIndex == model.tabBarIndex
&& background == model.background
&& clientParameters == model.clientParameters
&& customTimeoutTime == model.customTimeoutTime
&& extraParameters == model.extraParameters
&& analyticsData == model.analyticsData
&& fallbackResponse == model.fallbackResponse
}
}
extension ActionOpenPageModel: CustomDebugStringConvertible {
public var debugDescription: String {
if let requestURL {
return "\(Self.self) for \(pageType) @ \(requestURL)"
} else {
return "\(Self.self) for \(pageType)"
}
}
}

View File

@ -30,13 +30,4 @@ public struct ActionOpenSMSModel: ActionModelProtocol {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
// Default
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return model.extraParameters == extraParameters
&& model.analyticsData == analyticsData
&& model.phoneNumber == phoneNumber
&& model.message == message
}
}

View File

@ -60,13 +60,4 @@ open class ActionOpenUrlModel: ActionModelProtocol {
try container.encodeIfPresent(extraParameters, forKey: .extraParameters)
try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return extraParameters == model.extraParameters
&& analyticsData == model.analyticsData
&& browserUrl == model.browserUrl
&& appURL == model.appURL
&& appURLOptions == model.appURLOptions
}
}

View File

@ -25,12 +25,4 @@ public struct ActionPreviousSubmitModel: ActionModelProtocol {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
// Default
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return model.actionType == actionType
&& model.extraParameters == extraParameters
&& model.analyticsData == analyticsData
}
}

View File

@ -25,16 +25,11 @@ open class ActionRestartHandler: MVMCoreActionHandlerProtocol {
return
}
continuation.resume(throwing: MVMCoreError.errorObject(error))
return
}
if let sessionObject = MVMCoreSessionObject.sharedGlobal() {
if model.hardReset {
sessionObject.clearPersistentCache()
}
} else {
// Restarts the app (forcing any passed in page types).
sessionObject.restartSession(withPageType: model.pageType, request: model.requestURL, parameters: model.extraParameters?.toJSON(), clearAllVariables: true)
MVMCoreSessionObject.sharedGlobal()?.restartSession(withPageType: model.pageType, request: model.requestURL, parameters: model.extraParameters?.toJSON(), clearAllVariables: true)
continuation.resume()
}
continuation.resume()
})
}
}

View File

@ -16,7 +16,6 @@ public struct ActionRestartModel: ActionModelProtocol {
public static var identifier: String = "restart"
public var actionType: String = ActionRestartModel.identifier
public var requestURL: URL?
@DecodableDefault.True public var hardReset: Bool
public var extraParameters: JSONValueDictionary?
public var analyticsData: JSONValueDictionary?
@ -27,20 +26,10 @@ public struct ActionRestartModel: ActionModelProtocol {
// MARK: - Initializer
//--------------------------------------------------
public init(_ pageType: String? = nil, _ requestUrl: URL? = nil, hardReset: Bool? = nil, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
public init(_ pageType: String? = nil, _ requestUrl: URL? = nil, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
self.pageType = pageType
self.requestURL = requestUrl
self.extraParameters = extraParameters
self.analyticsData = analyticsData
self.hardReset = hardReset ?? true
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return extraParameters == model.extraParameters
&& analyticsData == model.analyticsData
&& requestURL == model.requestURL
&& pageType == model.pageType
&& hardReset == model.hardReset
}
}

View File

@ -25,10 +25,4 @@ public struct ActionSettingModel: ActionModelProtocol {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return extraParameters == model.extraParameters
&& analyticsData == model.analyticsData
}
}

View File

@ -6,7 +6,7 @@
// Copyright © 2020 myverizon. All rights reserved.
//
public struct ActionShareItemModel: Codable, Equatable {
public struct ActionShareItemModel: Codable {
public enum SharedType: String, Codable {
case text
@ -14,14 +14,14 @@ public struct ActionShareItemModel: Codable, Equatable {
}
public var type: SharedType
public var value: AnyHashable // Common Equatable type between String and URL.
public var value: Any
private enum CodingKeys: String, CodingKey {
case type
case value
}
public init(type: SharedType, value: AnyHashable) {
public init(type: SharedType, value: Any) {
self.type = type
self.value = value
}
@ -47,11 +47,6 @@ public struct ActionShareItemModel: Codable, Equatable {
try container.encode(value as! URL, forKey: .value)
}
}
public static func == (lhs: ActionShareItemModel, rhs: ActionShareItemModel) -> Bool {
return lhs.type == rhs.type
&& lhs.value == rhs.value
}
}
public struct ActionShareModel: ActionModelProtocol {
@ -106,7 +101,7 @@ public struct ActionShareModel: ActionModelProtocol {
private init(deprecatedFrom decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: DeprecatedCodingKeys.self)
let type = try typeContainer.decode(ActionShareItemModel.SharedType.self, forKey: .sharedType)
var value: AnyHashable
var value: Any
switch type {
case .url:
value = try typeContainer.decode(URL.self, forKey: .sharedText)
@ -121,11 +116,4 @@ public struct ActionShareModel: ActionModelProtocol {
try container.encode(actionType, forKey: .actionType)
try container.encode(items, forKey: .items)
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return extraParameters == model.extraParameters
&& analyticsData == model.analyticsData
&& items == model.items
}
}

View File

@ -85,9 +85,9 @@ public protocol MVMCoreJSONActionHandlerProtocol: MVMCoreActionHandlerProtocol {
open func handleAction(with model: ActionModelProtocol, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) async throws {
try Task.checkCancellation()
var (additionalData, uuid) = MVMCoreActionHandler.setUUID(additionalData: additionalData)
MVMCoreActionHandler.log(string: "Begin Action: \(model)", additionalData: additionalData)
MVMCoreActionHandler.log(string: "Begin Action: \(model.actionType)", additionalData: additionalData)
defer {
MVMCoreActionHandler.log(string: "End Action: \(model)", additionalData: additionalData)
MVMCoreActionHandler.log(string: "End Action: \(model.actionType)", additionalData: additionalData)
}
let json = try additionalData.removeValue(forKey: jsonKey) as? [AnyHashable : Any] ?? MVMCoreActionHandler.convertActionToJSON(model)
@ -148,18 +148,12 @@ public protocol MVMCoreJSONActionHandlerProtocol: MVMCoreActionHandlerProtocol {
}
static public func log(string: String, additionalData: [AnyHashable: Any]?) {
MVMCoreLoggingHandler.shared()?.handleDebugMessage("ActionHandler: UUID: \(getUUID(additionalData: additionalData) ?? "untracked"), \(string)", category: String(describing: Self.self))
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ActionHandler: UUID: \(String(describing: getUUID(additionalData: additionalData))), \(string)")
}
fileprivate func logActionError(_ error: Error, _ actionType: String?, _ additionalData: [AnyHashable: Any]?, _ delegateObject: DelegateObject?) {
MVMCoreActionHandler.log(string: "Failed Action: Error \(error)", additionalData: additionalData)
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: MVMCoreActionHandler.getErrorLocation(with: delegateObject?.actionDelegate, actionType: actionType ?? "noAction")) {
if let fromBridge = additionalData?["fromBridge"] as? Bool, fromBridge, let browserUrl = additionalData?["browserUrl"] as? String {
errorObject.requestUrl = browserUrl
}
if let humanReadableMessage = (error as? HumanReadableDecodingErrorProtocol)?.readableDescription {
errorObject.messageToLog = "Failed to decode the \(actionType ?? "") action model. " + humanReadableMessage
}
defaultHandleActionError(errorObject, additionalData: additionalData)
}
}
@ -182,7 +176,7 @@ public protocol MVMCoreJSONActionHandlerProtocol: MVMCoreActionHandlerProtocol {
} catch {
let actionType = json?.optionalStringForKey(KeyActionType)
switch error {
case is ModelRegistry.Error, is DecodingError:
case ModelRegistry.Error.decoderError, is DecodingError:
MVMCoreLoggingHandler.shared()?.logCoreEvent(.actionFailedToDecode(pageType: pageType(from: delegateObject), error: error))
logActionError(error, actionType, additionalData, delegateObject)
case ModelRegistry.Error.decoderErrorModelNotMapped:

View File

@ -9,8 +9,7 @@
import Foundation
/// A model for UIApplication.OpenExternalURLOptionsKey
open class OpenUrlOptionsModel: Codable, Equatable {
open class OpenUrlOptionsModel: Codable {
public var options: [UIApplication.OpenExternalURLOptionsKey: Any]
//--------------------------------------------------
@ -43,16 +42,4 @@ open class OpenUrlOptionsModel: Codable, Equatable {
try container.encode(universalLinksValue, forKey: .universalLinksOnly)
}
}
public static func == (lhs: OpenUrlOptionsModel, rhs: OpenUrlOptionsModel) -> Bool {
return lhs.options.allSatisfy { pair in
switch(pair.key) {
case .universalLinksOnly:
return rhs.options[pair.key] as? Bool == pair.value as? Bool
default:
return true
}
}
}
}

View File

@ -52,7 +52,7 @@
- (void)getJsonData:(nonnull MVMCoreRequestParameters *)requestParameters forUrl:(nonnull NSURL *)url completion:(nonnull void (^)(NSData * _Nullable data, MVMCoreErrorObject *_Nullable error))completion;
- (void)getInitialParametersExcludingSections:(NSSet<NSString *> *_Nullable)excludeSections actionId:(nonnull NSString *)actionId completion:(nonnull void (^)(NSDictionary *_Nullable parameters))completion NS_SWIFT_NAME(initialParameters(excludingSections:actionId:completion:));
- (void)getInitialParametersExcludingSections:(NSSet<NSString *> *_Nullable)excludeSections completion:(nonnull void (^)(NSDictionary *_Nullable parameters))completion NS_SWIFT_NAME(initialParameters(excludingSections:completion:));
// Creates a request object with the given parameters.
- (void)transformToRequestWithParameters:(nonnull MVMCoreRequestParameters *)requestParameters completion:(nonnull void (^)(NSURLRequest * _Nullable request, MVMCoreErrorObject *_Nullable error))completion;

View File

@ -190,7 +190,7 @@
}
}
- (void)getInitialParametersExcludingSections:(NSSet<NSString *> *)excludeSections actionId:(NSString *)actionId completion:(void (^)(NSDictionary * _Nullable))completion {}
- (void)getInitialParametersExcludingSections:(NSSet<NSString *> *_Nullable)excludeSections completion:(nonnull void (^)(NSDictionary *_Nullable parameters))closure {}
- (void)getJsonDictionary:(nonnull MVMCoreRequestParameters *)requestParameters completion:(nonnull void (^)(NSDictionary * _Nullable jsonDictionary))completion {
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
@ -206,7 +206,7 @@
}
// Sets up the Initial parameters.
[self getInitialParametersExcludingSections:requestParameters.excludedInitialParameters actionId:requestParameters.identifier ?: [NSUUID UUID].UUIDString completion:^(NSDictionary * _Nullable initialParameters) {
[self getInitialParametersExcludingSections:requestParameters.excludedInitialParameters completion:^(NSDictionary * _Nullable initialParameters) {
if (initialParameters) {
[parameters setObject:initialParameters forKey:@"InitialParams"];
}
@ -232,7 +232,7 @@
return;
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
MVMCoreNetworkLog(@"Request Parameters for URL %@:\n%@", [url absoluteString], jsonString);
MVMCoreLog(@"Request Parameters for URL %@:\n%@", [url absoluteString], jsonString);
#endif
// Standard condensed to send to the server.
@ -309,15 +309,15 @@
return nil;
}
MVMCoreNetworkLog(@"********************************* Cookie Sent *********************************");
MVMCoreLog(@"********************************* Cookie Sent *********************************");
[[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:request.URL] enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
MVMCoreNetworkLog(@"Cookie Name: %@, Cookie Value: %@, Domain: %@", obj.name, obj.value, obj.domain);
MVMCoreLog(@"Cookie Name: %@, Cookie Value: %@, Domain: %@", obj.name, obj.value, obj.domain);
}];
NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
MVMCoreNetworkLog(@"Request Time %f", [NSDate timeIntervalSinceReferenceDate] - startTime);
MVMCoreLog(@"Request Time %f", [NSDate timeIntervalSinceReferenceDate] - startTime);
NSDate *startTimeDate = [NSDate dateWithTimeIntervalSinceReferenceDate:startTime];
@ -330,7 +330,7 @@
[trackInfo setObject:error.localizedDescription forKey:@"error"];
}
MVMCoreNetworkLog(@"Set-Cookie %@ Value: %@", requestParameters.pageType, [(NSHTTPURLResponse *)response allHeaderFields][@"Set-Cookie"]);
MVMCoreLog(@"Set-Cookie %@ Value: %@", requestParameters.pageType, [(NSHTTPURLResponse *)response allHeaderFields][@"Set-Cookie"]);
id jsonObject = nil;
MVMCoreErrorObject *errorObject = nil;
@ -354,7 +354,7 @@
// Log the response pretty.
NSData *prettyData = [NSJSONSerialization dataWithJSONObject:jsonObject options:NSJSONWritingPrettyPrinted error:&error];
NSString *responseString = [[NSString alloc] initWithData:prettyData encoding:NSUTF8StringEncoding];
MVMCoreNetworkLog(@"Response for Request Page Type %@:\n%@",requestParameters.pageType, responseString);
MVMCoreLog(@"Response for Request Page Type %@:\n%@",requestParameters.pageType, responseString);
}
} else {
// Empty response.

View File

@ -44,9 +44,8 @@ public extension MVMCoreLoadRequestOperation {
@MainActor
func goToViewController(loadObject: MVMCoreLoadObject) async -> UIViewController? {
guard loadObject.requestParameters?.replaceViewIfOnStackElseLoadWithStyle == true,
loadObject.requestParameters?.replaceViewControllerIfOnStackGoToOnly == true,
let pageType = loadObject.pageType else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "\(type(of: self)): A new controller should be made. pageType:\(String(describing: loadObject.pageType))")
let pageType = loadObject.pageType else {
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "\(type(of: self)): A new controller should be made and any existing shouldn't be replaced. pageType:\(String(describing: loadObject.pageType))")
return nil
}
let template = loadObject.pageJSON?.optionalStringForKey("template")

View File

@ -86,7 +86,7 @@
// stop any loading animation we may have started
[self stopLoadingAnimationIfNeeded];
MVMCoreNetworkLog(@"Load Operation finished for page type %@, background load %@", self.requestParameters.pageType, @(self.backgroundLoad));
MVMCoreLog(@"Load Operation finished for page type %@, background load %@", self.requestParameters.pageType, @(self.backgroundLoad));
[super markAsFinished];
}
@ -107,7 +107,7 @@
}
- (void)main {
MVMCoreNetworkLog(@"Load Operation begun for page type %@, background load %@, delegate %@", self.requestParameters.pageType, @(self.backgroundLoad),self.delegateObject.loadDelegate);
MVMCoreLog(@"Load Operation begun for page type %@, background load %@, delegate %@", self.requestParameters.pageType, @(self.backgroundLoad),self.delegateObject.loadDelegate);
[self.requestParameters resolveURL:[MVMCoreSessionObject sharedGlobal]];
@ -139,10 +139,10 @@
// Log if loaded from cache.
if (pageFromCache) {
MVMCoreNetworkLog(@"loaded from cache page %@",[MVMCoreActionUtility formatDictionaryAsJSONString:pageFromCache]);
MVMCoreLog(@"loaded from cache page %@",[MVMCoreActionUtility formatDictionaryAsJSONString:pageFromCache]);
}
if (modulesFromCache) {
MVMCoreNetworkLog(@"loaded from cache modules %@",[MVMCoreActionUtility formatDictionaryAsJSONString:modulesFromCache]);
MVMCoreLog(@"loaded from cache modules %@",[MVMCoreActionUtility formatDictionaryAsJSONString:modulesFromCache]);
}
// Create a load object from any data we fetched.
@ -686,16 +686,7 @@
if (obj && [obj isKindOfClass:[NSDictionary class]]) {
NSDictionary *responseInfo = [obj dict:KeyResponseInfo];
//Response Info is missing but errorObject should be created with generic message + code + domain
if (responseInfo == nil) {
errorObject = [[MVMCoreLoadHandler sharedGlobal]
errorForLoadObject:loadObject
withTitle:nil
message:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorCritical]
messageToLog:[NSString stringWithFormat:@"Module %@ is missing a %@ object.", key, KeyResponseInfo]
code:ErrorCodeJSONNotDictionary
domain:ErrorDomainServer];
} else if (![ValueTypeSuccess isEqualToString:[responseInfo string:KeyType]]) {
if (![ValueTypeSuccess isEqualToString:[responseInfo string:KeyType]]) {
errorObject = [[MVMCoreLoadHandler sharedGlobal] attachLoadInformation:loadObject toError:
[[MVMCoreErrorObject alloc]
initWithTitle:[responseInfo stringForKey:KeyErrorHeading]
@ -705,6 +696,7 @@
domain:ErrorDomainServer
location:[[MVMCoreLoadHandler sharedGlobal] errorLocationForRequest:loadObject]]];
}
// Caches each dictionary from the array.
[[MVMCoreCache sharedCache] addModuleToCache:obj module:key queue:nil waitUntilFinished:YES completionBlock:NULL];
} else {
@ -830,7 +822,7 @@
return;
}
MVMCoreNetworkLog(@"Error: %@ %@ %@ %@ %@",[error stringErrorCode], error.domain, error.location,error.messageToDisplay, error.messageToLog);
MVMCoreLog(@"Error: %@ %@ %@ %@ %@",[error stringErrorCode], error.domain, error.location,error.messageToDisplay, error.messageToLog);
if (showAlertForErrorIfApplicable && (!loadObject.operation.backgroundLoad || loadObject.requestParameters.allowAlertsIfBackgroundRequest) && !loadObject.requestParameters.handleErrorsSilently && !error.silentError && !error.errorScreenError) {

View File

@ -79,13 +79,8 @@ typedef NS_ENUM(NSInteger, MFLoadStyle) {
// Determines how it is loaded.
@property (nonatomic) MFLoadStyle loadStyle;
/// Determines if we should search the stack for a controller with the same pageType or just load a new controller with style. Default true
@property (nonatomic) BOOL replaceViewIfOnStackElseLoadWithStyle;
/// Determines if, when replaceViewIfOnStackElseLoadWithStyle is true, we should create a new controller or only pop back to the existing controller. Default true
@property (nonatomic) BOOL replaceViewControllerIfOnStackGoToOnly;
// A flag for if a tab was pressed to cause this load. This will ensure that we do not load a new tab page.
@property (nonatomic) BOOL tabWasPressed;

View File

@ -29,7 +29,6 @@
// Default load style.
self.loadStyle = MFLoadStyleDefault;
self.replaceViewIfOnStackElseLoadWithStyle = YES;
self.replaceViewControllerIfOnStackGoToOnly = YES;
self.identifier = [[NSUUID UUID] UUIDString];
}
return self;
@ -190,7 +189,6 @@
copyObject.contextRoot = [self.contextRoot copy];
copyObject.loadStyle = self.loadStyle;
copyObject.replaceViewIfOnStackElseLoadWithStyle = self.replaceViewIfOnStackElseLoadWithStyle;
copyObject.replaceViewControllerIfOnStackGoToOnly = self.replaceViewControllerIfOnStackGoToOnly;
copyObject.noViewControllerToLoad = self.noViewControllerToLoad;
copyObject.dontDisplayViewController = self.dontDisplayViewController;
copyObject.noloadingOverlay = self.noloadingOverlay;

View File

@ -8,16 +8,13 @@
public protocol MVMCoreLoggingDelegateProtocol {
/// Can be used to log different actions performed by the core.
// Can be used to log different actions performed by the core.
func handleDebugMessage(_ message: String?)
/// Can be used to log a message under a particular cagetory.
func handleDebugMessage(_ message: String, category: String?)
/// Can be used to choose how to log error objects.
// Can be used to choose how to log error objects.
func addError(toLog errorObject: MVMCoreErrorObject)
/// Log that the load has finished.
// Log that the load has finished.
func logLoadFinished(_ loadObject: MVMCoreLoadObject?, loadedViewController: MVMCoreViewControllerProtocol?, error: MVMCoreErrorObject?)
}

View File

@ -7,7 +7,7 @@
//
public protocol ActionModelProtocol: ModelProtocol, CustomDebugStringConvertible {
public protocol ActionModelProtocol: ModelProtocol {
var actionType: String { get }
var extraParameters: JSONValueDictionary? { get set }
@ -33,15 +33,4 @@ public extension ActionModelProtocol {
static var categoryName: String {
return "\(ActionModelProtocol.self)"
}
var debugDescription: String {
return actionType
}
func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return model.actionType == actionType
&& model.extraParameters == extraParameters
&& model.analyticsData == analyticsData
}
}

View File

@ -29,11 +29,4 @@ public class ActionRunJavaScriptModel: ActionModelProtocol {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
public func isEqual(to model: any ModelComparisonProtocol) -> Bool {
guard let model = model as? Self else { return false }
return jsCallback == model.jsCallback
&& extraParameters == model.extraParameters
&& analyticsData == model.analyticsData
}
}

View File

@ -8,8 +8,7 @@
import Foundation
public class ClientParameterModel: Equatable, Codable {
public class ClientParameterModel: Codable {
var timeout: Double?
var list: [ClientParameterModelProtocol]
@ -34,9 +33,4 @@ public class ClientParameterModel: Equatable, Codable {
try container.encodeIfPresent(timeout, forKey: .timeout)
try container.encodeModels(list, forKey: .list)
}
public static func == (lhs: ClientParameterModel, rhs: ClientParameterModel) -> Bool {
return lhs.list.isEqual(to: rhs.list)
&& lhs.timeout == rhs.timeout
}
}

View File

@ -30,9 +30,4 @@ public extension ClientParameterModelProtocol {
static var categoryName: String {
return "\(ClientParameterModelProtocol.self)"
}
func isEqual(to model: any ModelProtocol) -> Bool {
guard let model = model as? Self else { return false }
return type == model.type
}
}

View File

@ -8,7 +8,7 @@
import Foundation
public protocol ModelProtocol: ModelComparisonProtocol, Codable {
public protocol ModelProtocol: Codable {
/// The key name of the molecule
static var identifier: String { get }
@ -50,102 +50,3 @@ extension ModelProtocol {
try unkeyedContainer.encode(self)
}
}
public protocol ModelComparisonProtocol {
/// Shallow checks if the current model is equal to another model. Defaults to false unless implemented otherwise.
func isEqual(to model: ModelComparisonProtocol) -> Bool
}
extension ModelComparisonProtocol {
public func isEqual(to model: ModelComparisonProtocol) -> Bool {
return false
}
}
public extension Optional {
/// Checks if the current model is equal to another model.
func isEqual(to model: ModelComparisonProtocol?) -> Bool {
guard let self = self as? ModelComparisonProtocol else {
return model == nil
}
guard let model = model else {
return false
}
return self.isEqual(to: model)
}
}
public extension Collection {
/// Checks if all the models in the given collection match another given collection.
func isEqual(to models: [ModelComparisonProtocol]) -> Bool {
guard count == models.count, let self = self as? [ModelComparisonProtocol] else { return false }
return models.indices.allSatisfy { index in
self[index].isEqual(to: models[index])
}
}
}
public extension Optional where Wrapped: Collection {
/// Checks if the current model is equal to another model.
func isEqual(to models: [ModelComparisonProtocol]?) -> Bool {
guard let self = self as? [ModelComparisonProtocol] else {
return models == nil
}
guard let models = models else {
return false
}
return self.isEqual(to: models)
}
}
public extension Optional {
/// Checks if
func matchExistence(with anotherOptional: Optional) -> Bool {
switch(self) {
case .none:
return anotherOptional == nil
case .some(_):
return anotherOptional != nil
}
}
}
func == (lhs: (any ModelComparisonProtocol)?, rhs: (any ModelComparisonProtocol)?) -> Bool {
switch (lhs, rhs) {
case (.some(let lhs), .some(let rhs)):
return lhs.isEqual(to: rhs)
case (.none, .none):
return true
default:
return false
}
}
func != (lhs: (any ModelComparisonProtocol)?, rhs: (any ModelComparisonProtocol)?) -> Bool {
return !(lhs == rhs)
}
func == (lhs: [any ModelComparisonProtocol]?, rhs: [any ModelComparisonProtocol]?) -> Bool {
switch (lhs, rhs) {
case (.some(let lhs), .some(let rhs)):
return lhs == rhs
case (.none, .none):
return true
default:
return false
}
}
func != (lhs: [any ModelComparisonProtocol]?, rhs: [any ModelComparisonProtocol]?) -> Bool {
return !(lhs == rhs)
}
func == (lhs: [any ModelComparisonProtocol], rhs: [any ModelComparisonProtocol]) -> Bool {
return lhs.elementsEqual(rhs, by: { (lhsElement, rhsElement) -> Bool in
return lhsElement == rhsElement
})
}
func != (lhs: [any ModelComparisonProtocol], rhs: [any ModelComparisonProtocol]) -> Bool {
return !(lhs == rhs)
}

View File

@ -50,9 +50,9 @@ public struct ModelRegistry {
/// A convenience wrapping function where error handling is managed within the class.
/// - Parameter type: Takes an object of ModelProtocol.self which is used to register
public static func register<M: ModelProtocol>(_ type: M.Type, allowsReplace: Bool = false) {
public static func register<M: ModelProtocol>(_ type: M.Type) {
do {
try throwable_register(type: type, allowsReplace: allowsReplace)
try throwable_register(type: type)
} catch {
handleError(error)
}
@ -211,7 +211,7 @@ public struct ModelRegistry {
public static func getCodingKey<T>(for type: T.Type) throws -> AnyCodingKey {
guard let category = getCategory(for: type) else {
throw ModelRegistry.Error.decoderOther(message: "Category hasnt been registered for the CodingKey for this type: \(String(describing: type.self))")
throw ModelRegistry.Error.decoderOther(message: "decodeModelsIfPresent only works for objects implementing the ModelProtocol protocol")
}
return AnyCodingKey(category.codingKey)

View File

@ -147,12 +147,6 @@ typedef void(^MVMCoreGetImageBlock)(UIImage * _Nullable, NSData * _Nullable, BOO
/// Clears the persistent JSON cache
- (void)clearPersistentJSONCache;
// Removes a json dictionary from the cache by pageType.
- (void)removePersistentJSONCacheForPageType:(nonnull NSString *)pageType pageJSON:(nonnull NSDictionary *)jsonDictionary;
// Removes a json dictionary from the cache by moduleType.
- (void)removePersistentModuleCacheForModule:(nonnull NSString *)moduleType moduleJSON:(nonnull NSDictionary *)jsonDictionary;
#pragma mark Image Functions
/// Register a bundle as one to search for images in.

View File

@ -181,14 +181,6 @@ static NSString * const STATIC_CACHE_COMPONENT = @"StaticCache.txt";
return [[PersistentCacheManager shared] loadForKey:moduleName path:[self getPathForPersistentCacheModule:moduleName] error:&error];
}
- (void)removePersistentJSONCacheForPageType:(nonnull NSString *)pageType pageJSON:(nonnull NSDictionary *)jsonDictionary {
[[PersistentCacheManager shared] removeForKey:pageType error:nil];
}
- (void)removePersistentModuleCacheForModule:(nonnull NSString *)moduleType moduleJSON:(nonnull NSDictionary *)jsonDictionary {
[[PersistentCacheManager shared] removeForKey:moduleType error:nil];
}
#pragma mark - Advanced Fetch
- (void)fetchJSONForPageType:(nullable NSString *)pageType queue:(nullable NSOperationQueue *)queue waitUntilFinished:(BOOL)waitUntilFinished completionHandler:(nonnull void (^)(NSDictionary * _Nullable jsonDictionary))completionHandler {
@ -323,7 +315,7 @@ static NSString * const STATIC_CACHE_COMPONENT = @"StaticCache.txt";
[weakSelf.pageTypeCache setObject:jsonDictionary forKey:pageType];
if (![self shouldPersistentlyCachePage:jsonDictionary pageType:pageType]) {
[self removePersistentJSONCacheForPageType:pageType pageJSON:jsonDictionary];
[[PersistentCacheManager shared] removeForKey:pageType error:nil];
return;
}
[self addPageToPersistentCache:jsonDictionary pageType:pageType expirationDate:[self getExpirationDateForJSON:jsonDictionary]];
@ -359,7 +351,7 @@ static NSString * const STATIC_CACHE_COMPONENT = @"StaticCache.txt";
[weakSelf.moduleCache setObject:jsonDictionary forKey:module];
if (![self shouldPersistentlyCacheModule:jsonDictionary module:module]) {
[self removePersistentModuleCacheForModule:module moduleJSON:jsonDictionary];
[[PersistentCacheManager shared] removeForKey:module error:nil];
return;
}
[self addModuleToPersistentCache:jsonDictionary moduleName:module expirationDate:[self getExpirationDateForJSON:jsonDictionary]];
@ -373,16 +365,6 @@ static NSString * const STATIC_CACHE_COMPONENT = @"StaticCache.txt";
- (void)addModulesToCache:(nonnull NSDictionary *)jsonDictionary queue:(nullable NSOperationQueue *)queue waitUntilFinished:(BOOL)waitUntilFinished completionBlock:(nullable void (^)(void))completionBlock {
[jsonDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if (![obj isKindOfClass:[NSDictionary class]]) {
MVMCoreErrorObject *error = [[MVMCoreErrorObject alloc]
initWithTitle:nil
messageToLog:[NSString stringWithFormat:@"Invalid module format. Cannot cache %@ as it's not an object", key]
code:ErrorCodeJSONNotDictionary
domain:ErrorDomainSystem
location:NSStringFromClass([self class])];
[MVMCoreLoggingHandler.sharedLoggingHandler addErrorToLog:error];
return;
}
[self addModuleToCache:obj module:key];
}];
__weak typeof(self) weakSelf = self;

View File

@ -7,31 +7,9 @@
//
import Foundation
import os
public protocol CoreLogging {
static var loggingCategory: String? { get }
var loggingPrefix: String { get }
}
public extension CoreLogging {
static var loggingCategory: String? { return nil }
var loggingPrefix: String {
return ""
}
static func debugLog(_ string: String) {
#if LOGGING
MVMCoreLoggingHandler.shared()?.handleDebugMessage(string, category: loggingCategory)
#endif
}
func debugLog(_ string: String) {
#if LOGGING
MVMCoreLoggingHandler.shared()?.handleDebugMessage("\(loggingPrefix)\(string)", category: Self.loggingCategory)
#endif
@objc public extension MVMCoreLoggingHandler {
@objc func print(with message: String) {
Swift.print(message)
}
}

View File

@ -7,28 +7,9 @@
//
import Foundation
import os
@objc open class MVMCoreLoggingHandler: NSObject, MVMCoreLoggingDelegateProtocol {
public static let standardCategory = "General"
private let logger = Logger(subsystem: "MVMCoreLogging", category: standardCategory)
private var loggerCache = [String: Logger]()
open func getLogger(category: String?) -> Logger {
if let category {
if let logger = loggerCache[category] {
return logger
} else {
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: category)
loggerCache[category] = logger
return logger
}
}
return logger
}
@objc(sharedLoggingHandler)
public static func shared() -> Self? {
return MVMCoreActionUtility.initializerClassCheck(MVMCoreObject.sharedInstance()?.loggingDelegate as? NSObject, classToVerify: self) as? Self
@ -48,57 +29,14 @@ import os
// MARK: - logging delegate
@objc open func handleDebugMessage(_ message: String?) {
#if LOGGING
guard let message = message else { return }
guard message.count < 1024 else {
logger.debug("\(message.prefix(300), privacy: .public)... <stdio>") // Send initial log to console.
print(message) // Print the whole on stdout.
return
}
logger.debug("\(message, privacy: .public)") // Assume that becaues this is a LOGGING build we want these messages to be unmasked.
// TODO: How do we split the messaging by Library and Subsystem?
#endif
}
@objc open func handleDebugMessage(_ message: String, category: String?) {
#if LOGGING
guard message.count < 1024 else {
getLogger(category: category).debug("\(message.prefix(300), privacy: .public)... <stdio>") // Send initial log to console.
print(message) // Print the whole on stdout.
return
}
getLogger(category: category).debug("\(message, privacy: .public)") // Assume that becaues this is a LOGGING build we want these messages to be unmasked.
#endif
}
open func handleWarningMessage(_ message: String, category: String?) {
#if LOGGING
guard message.count < 1024 else {
getLogger(category: category).warning("\(message.prefix(300), privacy: .public)... <stdio>") // Send initial log to console.
print(message) // Print the whole on stdout.
return
}
getLogger(category: category).warning("\(message, privacy: .public)") // Assume that becaues this is a LOGGING build we want these messages to be unmasked.
#endif
}
open func handleErrorMessage(_ message: String, category: String?) {
#if LOGGING
guard message.count < 1024 else {
getLogger(category: category).error("\(message.prefix(300), privacy: .public)... <stdio>") // Send initial log to console.
print(message) // Print the whole on stdout.
return
}
getLogger(category: category).error("\(message, privacy: .public)") // Assume that becaues this is a LOGGING build we want these messages to be unmasked.
guard let message = message else { return }
self.print(with: message)
#endif
}
@objc(addErrorToLog:)
open func addError(toLog errorObject: MVMCoreErrorObject) {
if errorObject.silentError {
handleWarningMessage(errorObject.messageToLog ?? errorObject.messageToDisplay ?? "Some error occurred.", category: "Handled Exception")
} else {
handleErrorMessage(errorObject.messageToLog ?? errorObject.messageToDisplay ?? "Some error occurred.", category: "Handled Exception")
}
// Subclass to handle.
}
open func logLoadFinished(_ loadObject: MVMCoreLoadObject?, loadedViewController: MVMCoreViewControllerProtocol?, error: MVMCoreErrorObject?) {}

View File

@ -8,11 +8,7 @@
#ifndef MVMCoreLoggingHandlerHelper_h
#define MVMCoreLoggingHandlerHelper_h
#define MVMCoreLog(fmt, ...) \
[MVMCoreLoggingHandler logDebugMessageWithDelegate:[NSString stringWithFormat:(@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__]];
#define MVMCoreNetworkLog(fmt, ...) \
[MVMCoreLoggingHandler.sharedLoggingHandler handleDebugMessage:[NSString stringWithFormat:(@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__] category: @"Network"];
#endif

View File

@ -68,9 +68,9 @@ open class NavigationOperation: MVMCoreOperation, UINavigationControllerDelegate
let index = navigationController.getIndexOfViewController(with: pageType) else {
return false
}
var viewControllers = Array(navigationController.viewControllers[...index])
var viewControllers = navigationController.viewControllers[...index]
viewControllers[index] = viewController
set(viewControllers: viewControllers, navigationController: navigationController, animated: animated)
set(viewControllers: Array(viewControllers), navigationController: navigationController, animated: animated)
return true
}
@ -110,8 +110,7 @@ open class NavigationOperation: MVMCoreOperation, UINavigationControllerDelegate
*/
@MainActor
open func set(viewControllers: [UIViewController], navigationController: UINavigationController, animated: Bool) {
guard viewControllers.count > 0,
navigationController.viewControllers != viewControllers else { // If the controller stack is the same, iOS will not call the delegate method of the change, causing the operation to hang.
guard viewControllers.count > 0 else {
markAsFinished()
return
}

View File

@ -38,9 +38,6 @@
/// Clears the session singleton. Creates a new session NSURLSession also.
- (void)clearSessionObject;
/// Clears any persistent cache related to the current session.
- (void)clearPersistentCache;
/// Copys string to clipboard and assigns self.clipboardString for validation
/// Should only be used when expected string is a secure string
-(void)copyStringToClipboard :(nullable NSString *)clipboardString;

View File

@ -53,6 +53,4 @@
self.session = [self createNSURLSession];
}
- (void)clearPersistentCache {}
@end

View File

@ -89,21 +89,21 @@ public extension NavigationHandler {
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: requestParameters.replaceViewIfOnStackElseLoadWithStyle, delegate: delegateObject?.presentationDelegate)
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: requestParameters.replaceViewIfOnStackElseLoadWithStyle, delegate: delegateObject?.presentationDelegate)
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: requestParameters.replaceViewIfOnStackElseLoadWithStyle, delegate: delegateObject?.presentationDelegate)
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: requestParameters.replaceViewIfOnStackElseLoadWithStyle, delegate: delegateObject?.presentationDelegate)
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: requestParameters.replaceViewIfOnStackElseLoadWithStyle, delegate: delegateObject?.presentationDelegate)
return NavigationOperation(with: .push(viewController: viewController, navigationController: navigationController, animated: shouldAnimate), tryToReplace: true, delegate: delegateObject?.presentationDelegate)
}
}

View File

@ -23,10 +23,8 @@
// Initialization code
self.title = title;
self.messageToDisplay = message;
self.messageToLog = message;
self.code = code;
self.domain = domain;
self.systemDomain = nil;
self.location = location;
self.date = [NSDate date];
self.silentError = YES;
@ -34,11 +32,6 @@
[MVMCoreDispatchUtility performSyncBlockOnMainThread:^{
self.applicationState = [UIApplication sharedApplication].applicationState;
}];
self.sessionId = nil;
self.requestId = nil;
self.requestUrl = nil;
self.serverResponseInfo = nil;
self.crashLog = nil;
}
return self;
}
@ -48,11 +41,9 @@
if (self = [super init]) {
// Initialization code
self.title = title;
self.messageToDisplay = nil;
self.messageToLog = messageToLog;
self.code = code;
self.domain = domain;
self.systemDomain = nil;
self.location = location;
self.date = [NSDate date];
self.silentError = YES;
@ -60,11 +51,6 @@
[MVMCoreDispatchUtility performSyncBlockOnMainThread:^{
self.applicationState = [UIApplication sharedApplication].applicationState;
}];
self.sessionId = nil;
self.requestId = nil;
self.requestUrl = nil;
self.serverResponseInfo = nil;
self.crashLog = nil;
}
return self;
}

View File

@ -1,69 +0,0 @@
//
// ReadableDecodingErrors.swift
// MVMCore
//
// Created by Kyle Hedden on 10/5/23.
// Copyright © 2023 myverizon. All rights reserved.
//
import Foundation
public protocol HumanReadableDecodingErrorProtocol {
var readableDescription: String { get }
}
extension JSONError: HumanReadableDecodingErrorProtocol {
public var readableDescription: String {
switch (self) {
case .other(let other):
if let other = other as? HumanReadableDecodingErrorProtocol {
return other.readableDescription
}
return description
default:
return description
}
}
}
extension ModelRegistry.Error: HumanReadableDecodingErrorProtocol {
public var readableDescription: String {
switch (self) {
case .decoderErrorModelNotMapped(let identifier, let codingKey, let codingPath) where identifier != nil && codingKey != nil && codingPath != nil:
return "Model identifier \"\(identifier!)\" is not mapped for \"\(codingKey!.stringValue)\" @ \(codingPath!.map { return $0.stringValue })"
case .decoderErrorObjectNotPresent(let codingKey, let codingPath):
return "Required model \"\(codingKey.stringValue)\" was not found @ \(codingPath.map { return $0.stringValue })"
case .decoderOther(let message):
return "An issue occurred while decoding: \(message)"
case .other(let message):
return "Registry error: \(message)"
default:
return "Registry error: \((self as NSError).localizedFailureReason ?? self.localizedDescription)"
}
}
}
extension DecodingError: HumanReadableDecodingErrorProtocol {
public var readableDescription: String {
switch (self) {
case .keyNotFound(let codingKey, let context):
return "Required key \(codingKey.stringValue) was not found @ \(context.codingPath.map { return $0.stringValue })"
case .valueNotFound(_, let context):
return "Value not found @ \(context.codingPath.map { return $0.stringValue })"
case .typeMismatch(_, let context):
return "Value type mismatch @ \(context.codingPath.map { return $0.stringValue })"
case .dataCorrupted(let context):
return "Data corrupted @ \(context.codingPath.map { return $0.stringValue })"
@unknown default:
return (self as NSError).localizedFailureReason ?? self.localizedDescription
}
}
}