diff --git a/LaunchGate.podspec b/LaunchGate.podspec index 657ddfd..40829bb 100755 --- a/LaunchGate.podspec +++ b/LaunchGate.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LaunchGate" - s.version = "1.1.1" + s.version = "1.1.4" s.summary = <<-SUMMARY LaunchGate makes it easy to let users know when an update to your app is available. SUMMARY diff --git a/Source/DefaultParser.swift b/Source/DefaultParser.swift index 610071b..90a8ceb 100755 --- a/Source/DefaultParser.swift +++ b/Source/DefaultParser.swift @@ -10,83 +10,85 @@ 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." + 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 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) - } - } + 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)") + return nil + } catch let error as NSError { + print("LaunchGate — Error: \(error.localizedDescription)") + + if let recoverySuggestion = error.localizedRecoverySuggestion { + print(recoverySuggestion) + } + return nil + } - return nil - } + 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 } + 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) - } + 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 } + 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) - } + 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 } + 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) - } + return UpdateConfiguration(version: version, message: message) + } } diff --git a/Source/DialogManager.swift b/Source/DialogManager.swift index ea68953..ae88b86 100755 --- a/Source/DialogManager.swift +++ b/Source/DialogManager.swift @@ -8,100 +8,120 @@ import Foundation +public protocol DialogManagerDelegate: class { + func didDismissAlertView() +} + +// Localization of strings + protocol Dialogable { - var message: String { get } + var message: String { get } } class DialogManager { - typealias RememberableDialogSubject = Dialogable & Rememberable + typealias RememberableDialogSubject = Dialogable & Rememberable + + enum DialogType { + case alert(blocking: Bool) + case optionalUpdate(updateURL: URL) + case requiredUpdate(updateURL: URL) + } + + var stringHandler: WordingHandler? + weak var delegate: DialogManagerDelegate? - enum DialogType { - case alert(blocking: Bool) - case optionalUpdate(updateURL: URL) - case requiredUpdate(updateURL: URL) - } + init(withWordingHandler wordingHandler: WordingHandler? = nil, + andDelegate delegate: DialogManagerDelegate? = nil) { + self.stringHandler = wordingHandler + self.delegate = delegate + } - func displayAlertDialog(_ alertConfig: RememberableDialogSubject, blocking: Bool) { - let dialog = createAlertController(.alert(blocking: blocking), message: alertConfig.message) + func displayAlertDialog(_ alertConfig: RememberableDialogSubject, blocking: Bool) { + let dialog = createAlertController(.alert(blocking: blocking), + message: stringHandler?.alertMessage ?? alertConfig.message) - displayAlertController(dialog) { () -> Void in - if !blocking { - Memory.remember(alertConfig) - } + displayAlertController(dialog) { () -> Void in + if !blocking { + Memory.remember(alertConfig) + } + } } - } - func displayRequiredUpdateDialog(_ updateConfig: Dialogable, updateURL: URL) { - let dialog = createAlertController(.requiredUpdate(updateURL: updateURL), message: updateConfig.message) + func displayRequiredUpdateDialog(_ updateConfig: Dialogable, updateURL: URL) { + let dialog = createAlertController(.requiredUpdate(updateURL: updateURL), + message: stringHandler?.requiredUpdateMessage ?? updateConfig.message) - displayAlertController(dialog, completion: nil) - } + displayAlertController(dialog, completion: nil) + } - func displayOptionalUpdateDialog(_ updateConfig: RememberableDialogSubject, updateURL: URL) { - let dialog = createAlertController(.optionalUpdate(updateURL: updateURL), message: updateConfig.message) + func displayOptionalUpdateDialog(_ updateConfig: RememberableDialogSubject, updateURL: URL) { + let dialog = createAlertController(.optionalUpdate(updateURL: updateURL), + message: stringHandler?.optionalUpdateMessage ?? updateConfig.message) - displayAlertController(dialog) { () -> Void in - Memory.remember(updateConfig) + displayAlertController(dialog) { () -> Void in + Memory.remember(updateConfig) + } } - } - // MARK: Custom Alert Controllers + // MARK: Custom Alert Controllers - func createAlertController(_ type: DialogType, message: String) -> UIAlertController { - let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert) + func createAlertController(_ type: DialogType, message: String) -> UIAlertController { + let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert) - switch type { - case let .alert(blocking): - if !blocking { + switch type { + case let .alert(blocking): + if !blocking { + alertController.addAction(dismissActon()) + } + + case let .optionalUpdate(updateURL): alertController.addAction(dismissActon()) + alertController.addAction(updateAction(updateURL)) + + case let .requiredUpdate(updateURL): + alertController.addAction(updateAction(updateURL)) } - case let .optionalUpdate(updateURL): - alertController.addAction(dismissActon()) - alertController.addAction(updateAction(updateURL)) + return alertController + } - case let .requiredUpdate(updateURL): - alertController.addAction(updateAction(updateURL)) + func displayAlertController(_ alert: UIAlertController, completion: (() -> Void)?) { + DispatchQueue.main.async { [] in + if let topViewController = self.topViewController() { + topViewController.present(alert, animated: true) { + if let completion = completion { + completion() + } + } + } + } } - return alertController - } + func topViewController() -> UIViewController? { + return UIApplication.shared.keyWindow?.rootViewController + } + + // MARK: Custom Alert Actions - func displayAlertController(_ alert: UIAlertController, completion: (() -> Void)?) { - DispatchQueue.main.async { [] in - if let topViewController = self.topViewController() { - topViewController.present(alert, animated: true) { - if let completion = completion { - completion() - } + private func dismissActon() -> UIAlertAction { + return UIAlertAction( + title: NSLocalizedString(stringHandler?.dismissTitle ?? "Dismiss", comment: "Button title for dismissing the update AlertView"), + style: .default) { _ in + self.delegate?.didDismissAlertView() } - } } - } - - func topViewController() -> UIViewController? { - return UIApplication.shared.keyWindow?.rootViewController - } - - // MARK: Custom Alert Actions - - private func dismissActon() -> UIAlertAction { - return UIAlertAction( - title: NSLocalizedString("Dismiss", comment: "Button title for dismissing the update AlertView"), - style: .default) { _ in } - } - - private func updateAction(_ updateURL: URL) -> UIAlertAction { - return UIAlertAction( - title: NSLocalizedString("Update", comment: "Button title for accepting the update AlertView"), - style: .default) { (_) -> Void in - if UIApplication.shared.canOpenURL(updateURL) { - DispatchQueue.main.async { [] in - UIApplication.shared.openURL(updateURL) + + private func updateAction(_ updateURL: URL) -> UIAlertAction { + return UIAlertAction( + title: NSLocalizedString(stringHandler?.downloadTitle ?? "Update", comment: "Button title for accepting the update AlertView"), + style: .default) { (_) -> Void in + if UIApplication.shared.canOpenURL(updateURL) { + DispatchQueue.main.async { [] in + UIApplication.shared.openURL(updateURL) + } } - } } - } + } } diff --git a/Source/LaunchGate.swift b/Source/LaunchGate.swift index e2337a6..6002111 100755 --- a/Source/LaunchGate.swift +++ b/Source/LaunchGate.swift @@ -8,127 +8,164 @@ import Foundation +/// Protocol for LaunchGate +public protocol LaunchGateDelegate: class { + func noUpdateHandler() +} + /// Custom internal error type typealias LaunchGateError = Error & CustomStringConvertible public class LaunchGate { - /// Parser to use when parsing the configuration file - public var parser: LaunchGateParser! + /// Parser to use when parsing the configuration file + public var parser: LaunchGateParser! - /// URI for the configuration file - var configurationFileURL: URL! + /// URI for the configuration file + var configurationFileURL: URL! - /// App Store URI ("itms-apps://itunes.apple.com/...") for the current app - var updateURL: URL! + /// App Store URI ("itms-apps://itunes.apple.com/...") for the current app + var updateURL: URL! - /// Manager object for the various alert dialogs - var dialogManager: DialogManager! + /// Manager object for the various alert dialogs + var dialogManager: DialogManager! - // MARK: - Public API + // MARK: - Public API - /** - Failable initializer. If either the `configURI` or `appStoreURI` are unable to be - converted into an `URL` (i.e. containing illegal URL characters) this initializer - will return `nil`. + open weak var delegate: LaunchGateDelegate? - - Parameters: - - configURI: URI for the configuration file - - appStoreURI: App Store URI ("itms-apps://itunes.apple.com/...") for the current app + /** + Failable initializer. If either the `configURI` or `appStoreURI` are unable to be + converted into an `URL` (i.e. containing illegal URL characters) this initializer + will return `nil`. - - Returns: A `LaunchGate` instance or `nil` - */ - public init?(configURI: String, appStoreURI: String) { - guard let configURL = URL(string: configURI) else { return nil } - guard let appStoreURL = URL(string: appStoreURI) else { return nil } + - Parameters: + - configURI: URI for the configuration file + - appStoreURI: App Store URI ("itms-apps://itunes.apple.com/...") for the current app - configurationFileURL = configURL - updateURL = appStoreURL - parser = DefaultParser() - dialogManager = DialogManager() - } + - Returns: A `LaunchGate` instance or `nil` + */ + public init?(configURI: String, appStoreURI: String, + wordingHandler: WordingHandler? = nil, + dialogDelegate: DialogManagerDelegate? = nil) { + guard let configURL = URL(string: configURI) else { return nil } + guard let appStoreURL = URL(string: appStoreURI) else { return nil } - /// Check the configuration file and perform any appropriate action. - public func check() { - performCheck(RemoteFileManager(remoteFileURL: (configurationFileURL as URL))) - } + configurationFileURL = configURL + updateURL = appStoreURL + parser = DefaultParser() + dialogManager = DialogManager(withWordingHandler: wordingHandler, andDelegate: dialogDelegate) - // MARK: - Internal API + print( + """ + 🍒 [LaunchGate] configurationFileUrl = \(configurationFileURL) + updateUrl = \(updateURL) + parser = \(parser) + dialogManager = \(dialogManager) + """ + ) + } - /** - Check the configuration file and perform any appropriate action, using - the provided `RemoteFileManager`. + /// Check the configuration file and perform any appropriate action. + public func check() { + performCheck(RemoteFileManager(remoteFileURL: (configurationFileURL as URL), andDelegate: self)) + } - - Parameter remoteFileManager: The `RemoteFileManager` to use to fetch the configuration file. - */ - func performCheck(_ remoteFileManager: RemoteFileManager) { - remoteFileManager.fetchRemoteFile { (jsonData) -> Void in - if let config = self.parser.parse(jsonData) { - self.displayDialogIfNecessary(config, dialogManager: self.dialogManager) - } + // MARK: - Internal API + + /** + Check the configuration file and perform any appropriate action, using + the provided `RemoteFileManager`. + + - Parameter remoteFileManager: The `RemoteFileManager` to use to fetch the configuration file. + */ + func performCheck(_ remoteFileManager: RemoteFileManager) { + remoteFileManager.fetchRemoteFile { (jsonData) -> Void in + if let config = self.parser.parse(jsonData) { + print("⚪️ [LaunchGate] Config available for remote file : \(config)") + self.displayDialogIfNecessary(config, dialogManager: self.dialogManager) + } else { + print("⚪️ [LaunchGate] No config available for remote file") + self.delegate?.noUpdateHandler() + } + } } - } - /** - Determine which dialog, if any, to display based on the parsed configuration. + /** + Determine which dialog, if any, to display based on the parsed configuration. - - Parameters: + - Parameters: - config: Configuration parsed from remote configuration file. - dialogManager: Manager object for the various alert dialogs - */ - func displayDialogIfNecessary(_ config: LaunchGateConfiguration, dialogManager: DialogManager) { - if let reqUpdate = config.requiredUpdate, let appVersion = currentAppVersion() { - if shouldShowRequiredUpdateDialog(reqUpdate, appVersion: appVersion) { - dialogManager.displayRequiredUpdateDialog(reqUpdate, updateURL: updateURL) - } - } else if let optUpdate = config.optionalUpdate, let appVersion = currentAppVersion() { - if shouldShowOptionalUpdateDialog(optUpdate, appVersion: appVersion) { - dialogManager.displayOptionalUpdateDialog(optUpdate, updateURL: updateURL) - } - } else if let alert = config.alert { - if shouldShowAlertDialog(alert) { - dialogManager.displayAlertDialog(alert, blocking: alert.blocking) - } + */ + func displayDialogIfNecessary(_ config: LaunchGateConfiguration, dialogManager: DialogManager) { + if let reqUpdate = config.requiredUpdate, let appVersion = currentAppVersion() { + if shouldShowRequiredUpdateDialog(reqUpdate, appVersion: appVersion) { + dialogManager.displayRequiredUpdateDialog(reqUpdate, updateURL: updateURL) + } else { + delegate?.noUpdateHandler() + } + } else if let optUpdate = config.optionalUpdate, let appVersion = currentAppVersion() { + if shouldShowOptionalUpdateDialog(optUpdate, appVersion: appVersion) { + dialogManager.displayOptionalUpdateDialog(optUpdate, updateURL: updateURL) + } else { + self.delegate?.noUpdateHandler() + } + } else if let alert = config.alert { + if shouldShowAlertDialog(alert) { + dialogManager.displayAlertDialog(alert, blocking: alert.blocking) + } else { + self.delegate?.noUpdateHandler() + } + } else { + self.delegate?.noUpdateHandler() + } } - } - /** - Determine if an alert dialog should be displayed, based on the configuration. + /** + Determine if an alert dialog should be displayed, based on the configuration. - - Parameter alertConfig: An `AlertConfiguration`, parsed from the configuration file. + - Parameter alertConfig: An `AlertConfiguration`, parsed from the configuration file. - - Returns: `true`, if an alert dialog should be displayed; `false`, if not. - */ - func shouldShowAlertDialog(_ alertConfig: AlertConfiguration) -> Bool { - return alertConfig.blocking || alertConfig.isNotRemembered() - } + - Returns: `true`, if an alert dialog should be displayed; `false`, if not. + */ + func shouldShowAlertDialog(_ alertConfig: AlertConfiguration) -> Bool { + return alertConfig.blocking || alertConfig.isNotRemembered() + } - /** - Determine if an optional update dialog should be displayed, based on the configuration. + /** + Determine if an optional update dialog should be displayed, based on the configuration. - - Parameter updateConfig: An `UpdateConfiguration`, parsed from the configuration file. + - Parameter updateConfig: An `UpdateConfiguration`, parsed from the configuration file. - - Returns: `true`, if an optional update should be displayed; `false`, if not. - */ - func shouldShowOptionalUpdateDialog(_ updateConfig: UpdateConfiguration, appVersion: String) -> Bool { - guard updateConfig.isNotRemembered() else { return false } + - Returns: `true`, if an optional update should be displayed; `false`, if not. + */ + func shouldShowOptionalUpdateDialog(_ updateConfig: UpdateConfiguration, appVersion: String) -> Bool { + guard updateConfig.isNotRemembered() else { return false } - return appVersion < updateConfig.version - } + return appVersion < updateConfig.version + } - /** - Determine if a required update dialog should be displayed, based on the configuration. + /** + Determine if a required update dialog should be displayed, based on the configuration. - - Parameter updateConfig: An `UpdateConfiguration`, parsed from the configuration file. + - Parameter updateConfig: An `UpdateConfiguration`, parsed from the configuration file. - - Returns: `true`, if a required update dialog should be displayed; `false`, if not. - */ - func shouldShowRequiredUpdateDialog(_ updateConfig: UpdateConfiguration, appVersion: String) -> Bool { - return appVersion < updateConfig.version - } + - Returns: `true`, if a required update dialog should be displayed; `false`, if not. + */ + func shouldShowRequiredUpdateDialog(_ updateConfig: UpdateConfiguration, appVersion: String) -> Bool { + return appVersion < updateConfig.version + } - func currentAppVersion() -> String? { - return Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String - } + func currentAppVersion() -> String? { + return Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String + } } + +extension LaunchGate: RemoteFileManagerDelegate { + func errorWithRemoteFileHandler() { + print("🔴 errorWithRemoteFileHandler()") + delegate?.noUpdateHandler() + } +} diff --git a/Source/RemoteFileManager.swift b/Source/RemoteFileManager.swift index 0e4f797..5b6b7d4 100755 --- a/Source/RemoteFileManager.swift +++ b/Source/RemoteFileManager.swift @@ -8,36 +8,45 @@ import Foundation +protocol RemoteFileManagerDelegate: class { + func errorWithRemoteFileHandler() +} + class RemoteFileManager { - let remoteFileURL: URL - - init(remoteFileURL: URL) { - self.remoteFileURL = remoteFileURL - } - - func fetchRemoteFile(_ callback: @escaping (Data) -> Void) { - performRemoteFileRequest(URLSession.shared, url: remoteFileURL, responseHandler: callback) - } - - 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)") - } - guard response != nil else { - print("LaunchGate - Error because there is no response") - return - } - guard let data = data else { - print("LaunchGate — Error: Remote configuration file response was empty.") - return - } - - responseHandler(data) + let remoteFileURL: URL + + weak var delegate: RemoteFileManagerDelegate? + + init(remoteFileURL: URL, andDelegate delegate: RemoteFileManagerDelegate? = nil) { + print("✡️ [RemoteFileManager] remoteFileURL : \(remoteFileURL) ") + self.remoteFileURL = remoteFileURL + self.delegate = delegate } - task.resume() - } + func fetchRemoteFile(_ callback: @escaping (Data) -> Void) { + performRemoteFileRequest(URLSession.shared, url: remoteFileURL, responseHandler: callback) + } + + 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)") + self.delegate?.errorWithRemoteFileHandler() + } + guard response != nil else { + print("🔽 LaunchGate - Error because there is no response") + self.delegate?.errorWithRemoteFileHandler() + return + } + guard let data = data else { + print("🔽 LaunchGate — Error: Remote configuration file response was empty.") + self.delegate?.errorWithRemoteFileHandler() + return + } + responseHandler(data) + } + task.resume() + } } diff --git a/Source/WordingHandler.swift b/Source/WordingHandler.swift new file mode 100644 index 0000000..240a202 --- /dev/null +++ b/Source/WordingHandler.swift @@ -0,0 +1,28 @@ +// +// WordingHandler.swift +// LaunchGate +// +// Created by Nicolas CHARVOZ on 03/09/2018. +// + +import Foundation + +open class WordingHandler { + var requiredUpdateMessage: String? + var optionalUpdateMessage: String? + var alertMessage: String? + var dismissTitle: String? + var downloadTitle: String? + + public init(requiredUpdateMessage: String?, + optionalUpdateMessage: String?, + alertMessage: String?, + dismissTitle: String?, + downloadTitle: String?) { + self.requiredUpdateMessage = requiredUpdateMessage + self.optionalUpdateMessage = optionalUpdateMessage + self.alertMessage = alertMessage + self.dismissTitle = dismissTitle + self.downloadTitle = downloadTitle + } +} diff --git a/StringHandler.swift b/StringHandler.swift new file mode 100644 index 0000000..a5caf94 --- /dev/null +++ b/StringHandler.swift @@ -0,0 +1,25 @@ +// +// StringHandler.swift +// LaunchGate +// +// Created by Nicolas CHARVOZ on 03/09/2018. +// + +import Foundation + +open class StringHandler { + var requiredUpdateMessage: String? + var optionalUpdateMessage: String? + var alertMessage: String? + var dismissTitle: String? + var downloadTitle: String? + + public init(requiredUpdateMessage: String?, optionalUpdateMessage: String?, + alertMessage: String?, dismissTitle: String?, downloadTitle: String?) { + self.requiredUpdateMessage = requiredUpdateMessage + self.optionalUpdateMessage = optionalUpdateMessage + self.alertMessage = alertMessage + self.dismissTitle = dismissTitle + self.downloadTitle = downloadTitle + } +}