diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..46c791e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "iBox/Resources/Version"] + path = iBox/Resources/Version + url = https://github.com/42Box/versioning diff --git a/iBox/Resources/Version b/iBox/Resources/Version new file mode 160000 index 0000000..172ce29 --- /dev/null +++ b/iBox/Resources/Version @@ -0,0 +1 @@ +Subproject commit 172ce2939fccd76558f254adfb7b02535f97113c diff --git a/iBox/Sources/AppDelegate.swift b/iBox/Sources/AppDelegate.swift index 1d9e30e..f21e00c 100644 --- a/iBox/Sources/AppDelegate.swift +++ b/iBox/Sources/AppDelegate.swift @@ -10,11 +10,11 @@ import CoreData @main class AppDelegate: UIResponder, UIApplicationDelegate { - - + let versioningHandler: VersioningHandler = VersioningHandler() func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. + + versioningHandler.checkAppVersion() return true } diff --git a/iBox/Sources/Model/VersionInfo.swift b/iBox/Sources/Model/VersionInfo.swift new file mode 100644 index 0000000..331a7cb --- /dev/null +++ b/iBox/Sources/Model/VersionInfo.swift @@ -0,0 +1,27 @@ +// +// Versioning.swift +// iBox +// +// Created by Chan on 2/29/24. +// + +// MARK: - VersionInfo +struct VersionInfo: Codable { + let version: [Version] + let url: URLClass +} + +// MARK: - URLClass +struct URLClass: Codable { + let updateURL: String? + + enum CodingKeys: String, CodingKey { + case updateURL = "updateUrl" + } +} + +// MARK: - Version +struct Version: Codable { + let id: Int + let latestVersion, minRequiredVersion: String +} diff --git a/iBox/Sources/Versioning/VersioningHandler.swift b/iBox/Sources/Versioning/VersioningHandler.swift new file mode 100644 index 0000000..b082c0f --- /dev/null +++ b/iBox/Sources/Versioning/VersioningHandler.swift @@ -0,0 +1,69 @@ +// +// VersioningHandler.swift +// iBox +// +// Created by Chan on 3/2/24. +// + +import UIKit + +class VersioningHandler { + + func checkAppVersion() { + let urlString = "https://my-json-server.typicode.com/42Box/versioning/db" + guard let url = URL(string: urlString) else { return } + + let task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in + guard let data = data, error == nil else { return } + + do { + let versionInfo = try JSONDecoder().decode(VersionInfo.self, from: data) + guard let latestVersion = versionInfo.version.first?.latestVersion, + let minRequiredVersion = versionInfo.version.first?.minRequiredVersion, + let updateUrl = versionInfo.url.updateURL else { return } + + DispatchQueue.main.async { + self?.compareVersion(latestVersion: latestVersion, minRequiredVersion: minRequiredVersion, updateUrl: updateUrl) + } + } catch { + print(error) + } + } + + task.resume() + } + + func compareVersion(latestVersion: String, minRequiredVersion: String, updateUrl: String) { + guard let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else { return } + + if appVersion.compare(minRequiredVersion, options: .numeric) == .orderedAscending { + showAlertForUpdate(updateUrl: updateUrl, isMandatory: true) + } else if appVersion.compare(latestVersion, options: .numeric) == .orderedAscending { + showAlertForUpdate(updateUrl: updateUrl, isMandatory: false) + } + } + + + func showAlertForUpdate(updateUrl: String, isMandatory: Bool) { + guard let windowScene = UIApplication.shared.connectedScenes.first(where: { $0 is UIWindowScene }) as? UIWindowScene, + let rootViewController = windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController else { + return + } + + + let message = isMandatory ? "새로운 버전이 필요합니다. 업데이트 하시겠습니까?" : "새로운 버전이 있습니다. 업데이트 하시겠습니까?" + let alert = UIAlertController(title: "업데이트 알림", message: message, preferredStyle: .alert) + + alert.addAction(UIAlertAction(title: "업데이트", style: .default, handler: { _ in + if let url = URL(string: updateUrl), UIApplication.shared.canOpenURL(url) { + UIApplication.shared.open(url) + } + })) + + if !isMandatory { + alert.addAction(UIAlertAction(title: "나중에", style: .cancel)) + } + + rootViewController.present(alert, animated: true) + } +}