diff --git a/MVMCore/MVMCore.xcodeproj/project.pbxproj b/MVMCore/MVMCore.xcodeproj/project.pbxproj index a524c2a..d4d1ef9 100644 --- a/MVMCore/MVMCore.xcodeproj/project.pbxproj +++ b/MVMCore/MVMCore.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 01DF561421F90ADC00CC099B /* Dictionary+MFConvenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF561321F90ADC00CC099B /* Dictionary+MFConvenience.swift */; }; 30349BF11FCCA78A00546A1E /* MVMCoreSessionTimeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 30349BEF1FCCA78A00546A1E /* MVMCoreSessionTimeHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; 30349BF21FCCA78A00546A1E /* MVMCoreSessionTimeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 30349BF01FCCA78A00546A1E /* MVMCoreSessionTimeHandler.m */; }; 881D26931FCC9D180079C521 /* MVMCoreErrorObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 881D268F1FCC9D180079C521 /* MVMCoreErrorObject.m */; }; @@ -142,6 +143,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 01DF561321F90ADC00CC099B /* Dictionary+MFConvenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dictionary+MFConvenience.swift"; sourceTree = ""; }; 0A11030B20864F94008ADD90 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; 0A11030C20864F9A008ADD90 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; 30349BEF1FCCA78A00546A1E /* MVMCoreSessionTimeHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreSessionTimeHandler.h; sourceTree = ""; }; @@ -339,6 +341,7 @@ 8876D5D91FB50AB000EB2E3D /* Categories */ = { isa = PBXGroup; children = ( + 01DF561321F90ADC00CC099B /* Dictionary+MFConvenience.swift */, 8876D5DA1FB50AB000EB2E3D /* NSArray+MFConvenience.h */, 8876D5DB1FB50AB000EB2E3D /* NSArray+MFConvenience.m */, 8876D5DC1FB50AB000EB2E3D /* NSDecimalNumber+MFConvenience.h */, @@ -689,6 +692,7 @@ TargetAttributes = { 8876D5C81FB50A9E00EB2E3D = { CreatedOnToolsVersion = 9.1; + LastSwiftMigration = 1010; ProvisioningStyle = Automatic; }; AF954914206EAEAD000095EC = { @@ -788,6 +792,7 @@ 8876D5F51FB50AB000EB2E3D /* UILabel+MFCustom.m in Sources */, AFBB96B31FBA3B590008D868 /* MVMCoreGetterUtility.m in Sources */, AF43A7071FC4D7A2008E9347 /* MVMCoreObject.m in Sources */, + 01DF561421F90ADC00CC099B /* Dictionary+MFConvenience.swift in Sources */, AFBB96B11FBA3B590008D868 /* MVMCoreDispatchUtility.m in Sources */, AFBB965B1FBA3A570008D868 /* FreeBeeUrlObject.m in Sources */, AFEA17A9209B6A1C00BC6740 /* MVMCoreBlockOperation.m in Sources */, @@ -934,6 +939,7 @@ isa = XCBuildConfiguration; buildSettings = { BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; @@ -951,6 +957,8 @@ PRODUCT_BUNDLE_IDENTIFIER = com.vzw.MVMCore; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -959,6 +967,7 @@ isa = XCBuildConfiguration; buildSettings = { BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; @@ -975,6 +984,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.vzw.MVMCore; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/MVMCore/MVMCore/Categories/Dictionary+MFConvenience.swift b/MVMCore/MVMCore/Categories/Dictionary+MFConvenience.swift new file mode 100644 index 0000000..fa54073 --- /dev/null +++ b/MVMCore/MVMCore/Categories/Dictionary+MFConvenience.swift @@ -0,0 +1,174 @@ +// +// Dictionary+MFConvenience.swift +// mobilefirst +// +// Created by Seshamani, Shreyas on 1/5/17. +// Copyright © 2017 Verizon Wireless. All rights reserved. +// + +import Foundation + +public extension Dictionary { + + /// Returns a Dictionary using the specified chain. An empty dictionary is returned if a dictionary for the chain does not exist + public func dictionaryWithChainOfKeysOrIndexes(_ keysOrIndexes: [Any]) -> [String : Any] { + + guard let dictionary = optionalDictionaryWithChainOfKeysOrIndexes(keysOrIndexes) else { + return [:] + } + return dictionary + } + + /// Returns an optional Dictionary using the specified chain. Returns nil if a dictionary for the chain does not exist + public func optionalDictionaryWithChainOfKeysOrIndexes (_ keysOrIndexes: [Any]) -> [String : Any]? { + + return objectChainOfKeysOrIndexes(keysOrIndexes) as? [String: Any] + } + + public func optionalDictionaryForKey(_ key: String) -> [String : Any]? { + + return objectChainOfKeysOrIndexes([key]) as? [String: Any] + } + + /// Returns a String using the specified chain. An empty string is returned if a string for the chain does not exist + public func stringWithChainOfKeysOrIndexes(_ keysOrIndexes:[Any]) -> String { + + guard let string = objectChainOfKeysOrIndexes(keysOrIndexes) as? String else { + return "" + } + return string + } + + public func stringOptionalWithChainOfKeysOrIndexes(_ keysOrIndexes:[Any]) -> String? { + return objectChainOfKeysOrIndexes(keysOrIndexes) as? String + } + + /// Returns an Array using the specified chain. Returns an empty array if an array for the chain does not exist + public func arrayForChainOfKeysOrIndexes(_ keysOrIndexes: [Any]) -> [Any] { + + guard let array = objectChainOfKeysOrIndexes(keysOrIndexes) as? [Any] else { + return [] + } + return array + } + + /// Returns a Dictionary after looking up the specified key. An empty dictionary is returned if a dictionary for the key does not exist + public func dictionaryForKey(_ key : String) -> [String : Any] { + + return dictionaryWithChainOfKeysOrIndexes([key]) + } + + /// Returns a String after looking up the specified key. An empty string will be returned if a string for the key does not exist + public func stringForkey(_ key: String) -> String { + + return stringWithChainOfKeysOrIndexes([key]) + } + + /// Returns a String after looking up the specified key. Nil will be returned if a string for the key does not exist + public func optionalStringForKey(_ key: String) -> String? { + return objectChainOfKeysOrIndexes([key]) as? String + } + + + /// Returns an Array after looking up the specified key. An empty array will be returned if an array for the key does not exist + public func arrayForKey(_ key : String) -> [Any] { + + return arrayForChainOfKeysOrIndexes([key]) + } + + /// Return a Bool after looking up the specified key. This will return false if the key does not exist + public func boolForKey(_ key : String) -> Bool { + + guard let bool = objectChainOfKeysOrIndexes([key]) as? Bool else { + return false + } + return bool + } + + /// Return a Bool after looking up the specified key. This will return false if the key does not exist + public func optionalBoolForKey(_ key : String) -> Bool? { + + guard let bool = objectChainOfKeysOrIndexes([key]) as? Bool else { + return nil + } + return bool + } + + public func lenientBoolForKey(_ key: String) -> Bool { + guard let key = key as? Key, let object = self[key] else { + return false + } + if let object = object as? NSNumber { + return object.boolValue + } else if let object = object as? NSString { + return object.boolValue + } + return false + } + + public func boolForChainOfKeysOrIndexes(_ keysOrIndexes:[Any])-> Bool { + guard let bool = objectChainOfKeysOrIndexes(keysOrIndexes) as? Bool else { + return false + } + return bool + } + + /// Return a float from a string created by looking up the specified key. This will return 0.0 if the key does not exist + public func floatForKey(_ key: String) -> Float { + + guard let floatValue = objectChainOfKeysOrIndexes([key]) as? Float else { + return 0.0 + } + + return floatValue + } + + public func floatFromStringForKey(_ key:String) -> Float { + + let stringValue = stringForkey(key) + + guard let floatValue = Float(stringValue) else { + return 0.0 + } + + return floatValue + } + + + public func int32ForKey(_ key:String) -> Int32 { + + guard let intValue = objectChainOfKeysOrIndexes([key]) as? Int32 else { + return 0 + } + + return intValue + } + + private func objectChainOfKeysOrIndexes(_ keysOrIndexes:[Any]) -> Any? { + + var previousObject : Any? = self + + for keyOrIndex in keysOrIndexes { + + if let nextDictionary = previousObject as? [String:Any], + let keyOrIndex = keyOrIndex as? String { + + previousObject = nextDictionary[keyOrIndex] + continue + } + + else if let nextArray = previousObject as? [Any], + let keyOrIndex = keyOrIndex as? Int { + + previousObject = nextArray[keyOrIndex] + continue + } + else { + previousObject = nil + break + } + } + + return previousObject + } +}