diff --git a/Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json
index b8236c6..19882d5 100755
--- a/Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -39,6 +39,11 @@
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
}
],
"info" : {
diff --git a/LaunchGate.xcodeproj/project.pbxproj b/LaunchGate.xcodeproj/project.pbxproj
index cb94d3e..8000acd 100755
--- a/LaunchGate.xcodeproj/project.pbxproj
+++ b/LaunchGate.xcodeproj/project.pbxproj
@@ -504,6 +504,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -555,6 +556,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
@@ -579,7 +581,6 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -599,7 +600,6 @@
PRODUCT_BUNDLE_IDENTIFIER = com.dtrenz.LaunchGate;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
- SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -611,7 +611,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.dtrenz.LaunchGateTests;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -623,7 +622,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.dtrenz.LaunchGateTests;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 4.0;
};
name = Release;
};
diff --git a/LaunchGate.xcodeproj/xcshareddata/xcschemes/LaunchGate.xcscheme b/LaunchGate.xcodeproj/xcshareddata/xcschemes/LaunchGate.xcscheme
index 8693ead..d2e7eb8 100755
--- a/LaunchGate.xcodeproj/xcshareddata/xcschemes/LaunchGate.xcscheme
+++ b/LaunchGate.xcodeproj/xcshareddata/xcschemes/LaunchGate.xcscheme
@@ -43,10 +43,10 @@
+ BlueprintIdentifier = "C5A878881C6A7A95004599C2"
+ BuildableName = "Example.app"
+ BlueprintName = "Example"
+ ReferencedContainer = "container:Example/Example.xcodeproj">
@@ -62,15 +62,6 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
-
-
-
-
diff --git a/Podfile b/Podfile
index d72d3d1..6ac182d 100755
--- a/Podfile
+++ b/Podfile
@@ -1,8 +1,6 @@
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
-pod 'SwiftLint'
-
target 'LaunchGateTests' do
platform :ios, '8.3'
inherit! :search_paths
diff --git a/Podfile.lock b/Podfile.lock
index 7323484..566362e 100755
--- a/Podfile.lock
+++ b/Podfile.lock
@@ -1,7 +1,7 @@
PODS:
- - Nimble (7.1.3)
- - Quick (1.3.1)
- - SwiftLint (0.26.0)
+ - Nimble (7.3.1)
+ - Quick (1.3.2)
+ - SwiftLint (0.27.0)
DEPENDENCIES:
- Nimble
@@ -15,10 +15,10 @@ SPEC REPOS:
- SwiftLint
SPEC CHECKSUMS:
- Nimble: 2839b01d1b31f6a6a7777a221f0d91cf52e8e27b
- Quick: d17304d58d0d169dd0bd1c6e5c28e3318de32a1a
- SwiftLint: f6b83e8d95ee1e91e11932d843af4fdcbf3fc764
+ Nimble: 04f732da099ea4d153122aec8c2a88fd0c7219ae
+ Quick: 2623cb30d7a7f41ca62f684f679586558f483d46
+ SwiftLint: 3207c1faa2240bf8973b191820a116113cd11073
-PODFILE CHECKSUM: 80b19f99959846e7855de4619381077e49a4e498
+PODFILE CHECKSUM: c66a903b4dd3d64e68e8dcb4170d38ac84ba0147
COCOAPODS: 1.5.3
diff --git a/Source/AlertConfiguration.swift b/Source/AlertConfiguration.swift
index 6528f1a..81717b4 100755
--- a/Source/AlertConfiguration.swift
+++ b/Source/AlertConfiguration.swift
@@ -7,10 +7,10 @@
import Foundation
-public struct AlertConfiguration: Dialogable, Rememberable {
+public struct AlertConfiguration: Decodable, Dialogable, Rememberable {
- var message = ""
- var blocking = false
+ let message: String
+ let blocking: Bool
init?(message: String, blocking: Bool) {
guard !message.isEmpty else { return nil }
diff --git a/Source/DefaultParser.swift b/Source/DefaultParser.swift
index 610071b..efccd9f 100755
--- a/Source/DefaultParser.swift
+++ b/Source/DefaultParser.swift
@@ -10,83 +10,14 @@ import Foundation
class DefaultParser: LaunchGateParser {
- typealias JSON = [String: AnyObject]
-
- enum Error: LaunchGateError {
- case unableToParseConfigurationObject
- case unableToParseAlert
- case unableToParseOptionalUpdate
- case unableToParseRequiredUpdate
-
- var description: String {
- switch self {
- case .unableToParseConfigurationObject:
- return "Unable to parse the configuration object (\"ios\") from JSON file."
- case .unableToParseAlert:
- return "Unable to parse the alert configuration from JSON file."
- case .unableToParseOptionalUpdate:
- return "Unable to parse the optional update configuration from JSON file."
- case .unableToParseRequiredUpdate:
- return "Unable to parse the required update configuration from JSON file."
+ func parse(_ jsonData: Data) -> LaunchGateConfiguration? {
+ do {
+ let decoder = JSONDecoder()
+ let result = try decoder.decode(LaunchGateConfiguration.self, from: jsonData)
+ return result
+ } catch let error {
+ print("LaunchGate — Error: \(error)")
}
+ return nil
}
- }
-
- func parse(_ jsonData: Data) -> LaunchGateConfiguration? {
- do {
- let jsonData = try JSONSerialization.jsonObject(with: jsonData, options: [])
- guard let json = jsonData as? JSON else { throw Error.unableToParseConfigurationObject }
- guard let config = json["ios"] else { throw Error.unableToParseConfigurationObject }
-
- var alert: AlertConfiguration?
- var optionalUpdate: UpdateConfiguration?
- var requiredUpdate: UpdateConfiguration?
-
- if let alertJSON = config["alert"] as? JSON {
- alert = try DefaultParser.parseAlert(alertJSON)
- }
-
- if let optionalUpdateJSON = config["optionalUpdate"] as? JSON {
- optionalUpdate = try DefaultParser.parseOptionalUpdate(optionalUpdateJSON)
- }
-
- if let requiredUpdateJSON = config["requiredUpdate"] as? JSON {
- requiredUpdate = try DefaultParser.parseRequiredUpdate(requiredUpdateJSON)
- }
-
- return LaunchGateConfiguration(alert: alert, optionalUpdate: optionalUpdate, requiredUpdate: requiredUpdate)
- } catch let error as DefaultParser.Error {
- print("LaunchGate — Error: \(error)")
- } catch let error as NSError {
- print("LaunchGate — Error: \(error.localizedDescription)")
-
- if let recoverySuggestion = error.localizedRecoverySuggestion {
- print(recoverySuggestion)
- }
- }
-
- return nil
- }
-
- private static func parseAlert(_ json: JSON) throws -> AlertConfiguration? {
- guard let message = json["message"] as? String else { throw Error.unableToParseAlert }
- guard let blocking = json["blocking"] as? Bool else { throw Error.unableToParseAlert }
-
- return AlertConfiguration(message: message, blocking: blocking)
- }
-
- private static func parseOptionalUpdate(_ json: JSON) throws -> UpdateConfiguration? {
- guard let version = json["optionalVersion"] as? String else { throw Error.unableToParseOptionalUpdate }
- guard let message = json["message"] as? String else { throw Error.unableToParseOptionalUpdate }
-
- return UpdateConfiguration(version: version, message: message)
- }
-
- private static func parseRequiredUpdate(_ json: JSON) throws -> UpdateConfiguration? {
- guard let version = json["minimumVersion"] as? String else { throw Error.unableToParseRequiredUpdate }
- guard let message = json["message"] as? String else { throw Error.unableToParseRequiredUpdate }
-
- return UpdateConfiguration(version: version, message: message)
- }
-
}
diff --git a/Source/DialogManager.swift b/Source/DialogManager.swift
index ea68953..048c7cc 100755
--- a/Source/DialogManager.swift
+++ b/Source/DialogManager.swift
@@ -7,6 +7,7 @@
//
import Foundation
+import UIKit
protocol Dialogable {
var message: String { get }
@@ -40,7 +41,6 @@ class DialogManager {
func displayOptionalUpdateDialog(_ updateConfig: RememberableDialogSubject, updateURL: URL) {
let dialog = createAlertController(.optionalUpdate(updateURL: updateURL), message: updateConfig.message)
-
displayAlertController(dialog) { () -> Void in
Memory.remember(updateConfig)
}
diff --git a/Source/LaunchGate.swift b/Source/LaunchGate.swift
index e2337a6..53e0950 100755
--- a/Source/LaunchGate.swift
+++ b/Source/LaunchGate.swift
@@ -25,6 +25,7 @@ public class LaunchGate {
/// Manager object for the various alert dialogs
var dialogManager: DialogManager!
+ //var config: LaunchGateConfiguration!
// MARK: - Public API
/**
@@ -50,7 +51,7 @@ public class LaunchGate {
/// Check the configuration file and perform any appropriate action.
public func check() {
- performCheck(RemoteFileManager(remoteFileURL: (configurationFileURL as URL)))
+ performCheck(RemoteFileManager(remoteFileURL: (configurationFileURL)))
}
// MARK: - Internal API
@@ -63,7 +64,7 @@ public class LaunchGate {
*/
func performCheck(_ remoteFileManager: RemoteFileManager) {
remoteFileManager.fetchRemoteFile { (jsonData) -> Void in
- if let config = self.parser.parse(jsonData) {
+ if let config: LaunchGateConfiguration = self.parser.parse(jsonData) {
self.displayDialogIfNecessary(config, dialogManager: self.dialogManager)
}
}
diff --git a/Source/LaunchGateConfiguration.swift b/Source/LaunchGateConfiguration.swift
index 19aa168..77c1ceb 100755
--- a/Source/LaunchGateConfiguration.swift
+++ b/Source/LaunchGateConfiguration.swift
@@ -9,7 +9,7 @@
import Foundation
/// The configuration object that should be created as the result of parsing the remote configuration file.
-public struct LaunchGateConfiguration {
+public struct LaunchGateConfiguration: Decodable {
/// An `AlertConfiguration`, parsed from the configuration file.
var alert: AlertConfiguration?
@@ -20,4 +20,17 @@ public struct LaunchGateConfiguration {
/// A required `UpdateConfiguration`, parsed from the configuration file.
var requiredUpdate: UpdateConfiguration?
+ public init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: IOSCodingKeys.self)
+ let iosContainer = try container.nestedContainer(keyedBy: IOSCodingKeys.self, forKey: .ios)
+ alert = try iosContainer.decodeIfPresent(AlertConfiguration.self, forKey: .alert)
+ optionalUpdate = try iosContainer.decodeIfPresent(UpdateConfiguration.self, forKey: .optionalUpdate)
+ requiredUpdate = try iosContainer.decodeIfPresent(UpdateConfiguration.self, forKey: .requiredUpdate)
+ }
+ enum IOSCodingKeys: String, CodingKey {
+ case ios
+ case alert
+ case optionalUpdate
+ case requiredUpdate
+ }
}
diff --git a/Source/RemoteFileManager.swift b/Source/RemoteFileManager.swift
index 0e4f797..567b51a 100755
--- a/Source/RemoteFileManager.swift
+++ b/Source/RemoteFileManager.swift
@@ -23,7 +23,7 @@ class RemoteFileManager {
func performRemoteFileRequest(_ session: URLSession, url: URL, responseHandler: @escaping (_ data: Data) -> Void) {
let task = session.dataTask(with: url) { data, response, error in
if let error = error {
- print("LaunchGate — Error: \(error.localizedDescription)")
+ print("LaunchGate — Error2: \(error.localizedDescription)")
}
guard response != nil else {
print("LaunchGate - Error because there is no response")
diff --git a/Source/UpdateConfiguration.swift b/Source/UpdateConfiguration.swift
index de4088a..5a59f27 100755
--- a/Source/UpdateConfiguration.swift
+++ b/Source/UpdateConfiguration.swift
@@ -8,10 +8,9 @@
import Foundation
-public struct UpdateConfiguration: Dialogable, Rememberable {
-
- var version = ""
- var message = ""
+public struct UpdateConfiguration: Decodable, Dialogable, Rememberable {
+ var version: String
+ var message: String
init?(version: String, message: String) {
guard !version.isEmpty else { return nil }
@@ -20,6 +19,29 @@ public struct UpdateConfiguration: Dialogable, Rememberable {
self.version = version
self.message = message
}
+ public init(from decoder: Decoder) throws {
+ let optionalKeyedContainer = try decoder.container(keyedBy: OptionalCodingKeys.self)
+ let requiredKeyedContainer = try decoder.container(keyedBy: RequiredCodingKeys.self)
+ do {
+ version = try optionalKeyedContainer.decode(String.self, forKey: .version)
+ message = try optionalKeyedContainer.decode(String.self, forKey: .message)
+ } catch {
+ do {
+ version = try requiredKeyedContainer.decode(String.self, forKey: .version)
+ message = try requiredKeyedContainer.decode(String.self, forKey: .message)
+ } catch {
+ throw error
+ }
+ }
+ }
+ enum OptionalCodingKeys: String, CodingKey {
+ case version = "optionalVersion"
+ case message
+ }
+ enum RequiredCodingKeys: String, CodingKey {
+ case version = "minimumVersion"
+ case message
+ }
// MARK: Rememberable Protocol Methods