ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

์–ดํ”Œ์„ ์‹คํ–‰ํ• ๋•Œ ํŠน์ • ๋ฒ„์ „๋ณด๋‹ค ๋‚ฎ์„ ๊ฒฝ์šฐ

์—…๋ฐ์ดํŠธ๋ฅผ ๊ฐ•์ œ๋กœ ์š”๊ตฌํ•˜๋ฉฐ ์•ฑ์Šคํ† ์–ด๋กœ ํŽ˜์ด์ง€๋ฅผ ๋„์šฐ๋„๋ก ํ•˜๋Š” ์ž‘์—… ๊ตฌํ˜„์ค‘ ์ƒ๊ธด ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

 

์ฒ˜์Œ์— ๋ฒ„์ „์„ String ๋ฌธ์ž์—ด์˜ ๋น„๊ต ์—ฐ์‚ฐ์ž๋ฅผ ํ†ตํ•ด ์ž‘์—…์„ ํ†ตํ•ด ์–ดํ”Œ ์ตœ์†Œ ๋ฒ„์ „ ๋ณด๋‹ค ๋†’์€์ง€ ํŒ๋‹จํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

 

๋งŒ์•ฝ

 

ํ˜„์žฌ ์–ดํ”Œ ๋ฒ„์ „์ด 1.0.9

์–ดํ”Œ ์ตœ์†Œ ๋ฒ„์ „ 1.0.6

 

์ผ ๊ฒฝ์šฐ

 

 

 

"1.0.9" > "1.0.6" // true

์ด๋Ÿฌ๋ฉด ํ˜„์žฌ ๋ฒ„์ „์ด ์–ดํ”Œ ์ตœ์†Œ๋ฒ„์ „ ๋ณด๋‹ค ๋†’๋‹ค๊ณ  ํŒ๋‹จ๋˜์–ด ์—…๋ฐ์ดํŠธ ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

 

 

ํ•˜์ง€๋งŒ ๋งŒ์•ฝ 

ํ˜„์žฌ ์–ดํ”Œ ๋ฒ„์ „์ด "1.0.10" ์ผ ๊ฒฝ์šฐ

"1.0.10" > "1.0.6" // false 

 

์ด๋Ÿฐ์‹์œผ๋กœ false ๊ฐ€ ๋˜๋ฏ€๋กœ ์•ฑ์Šคํ† ์–ด๋กœ ์—ฐ๊ฒฐํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ

'Compare' ๋ผ๋Š” String ๋‚ด๋ถ€์˜ method๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

https://developer.apple.com/documentation/foundation/nsstring/1414082-compare

 

compare(_:) | Apple Developer Documentation

Returns the result of invoking with no options and the receiver’s full extent as the range.

developer.apple.com

 

 

 

๋น„๊ต ์˜ต์…˜ ํƒ€์ž…์€ numeric์ด๊ณ , ์„ค๋ช…๊ธ€์˜ Name2.txt < Name7.txt < Name25.txt ๋ฅผ ๋ณด๋ฉด

๋ฒ„์ „ ๋น„๊ต์— ์ ํ•ฉํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

๊ฒฐ๋ก ์€ Compare๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ–ˆ๊ณ 

 

์•„๋ž˜๋Š” ๋ฒ„์ „์„ ๊ฐ€์ ธ์™€์„œ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฐ•์ œํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค

(์ฐธ๊ณ ๋กœ ์ œ ์ฝ”๋“œ์—์„œ๋Š” ์—…๋ฐ์ดํŠธ ์ตœ์†Œ ๋ฒ„์ „์„ ์•ฑ ์Šคํ† ์–ด์— ๋ฐฐํฌ๋˜์–ด์žˆ๋Š” ๋ฒ„์ „์œผ๋กœ ํ•˜์˜€์Šต๋‹ˆ๋‹ค)

 

 

-> ์•ฑ์Šคํ† ์–ด์— ์˜ฌ๋ผ๊ฐ€์žˆ๋Š” ๋ฒ„์ „๋ณด๋‹ค ๋‚ฎ์€ ๋ฒ„์ „์˜ ์•ฑ์ผ ๊ฒฝ์šฐ ์‹คํ–‰์‹œ ์•ฑ์Šคํ† ์–ด๋กœ ์œ ๋„ํ•˜๋„๋ก

 

 

 

 

import UIKit

enum VersionError: Error {
  case invalidResponse, invalidBundleInfo
}

class AppVersionCheck {
    
    static let shared = AppVersionCheck()
    private init() { }
    // ์ฝ”๋“œ์ž‘์„ฑ
    static func isUpdateAvailable(completion: @escaping (Bool?, Error?) -> Void) throws -> URLSessionDataTask {
        guard let info = Bundle.main.infoDictionary,
            let currentVersion = info["CFBundleShortVersionString"] as? String, // ํ˜„์žฌ ๋ฒ„์ „ ๊ฐ€์ ธ์˜ค๊ธฐ
            let identifier = info["CFBundleIdentifier"] as? String, // ์•ฑ ๋ฒˆ๋“ค์•„์ด๋”” ๊ฐ€์ ธ์˜ค๊ธฐ
            let url = URL(string: "http://itunes.apple.com/kr/lookup?bundleId=\(identifier)") else {
                throw VersionError.invalidBundleInfo
            }
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            do {
                if let error = error { throw error }
                guard let data = data else { throw VersionError.invalidResponse }
                let json = try JSONSerialization.jsonObject(with: data, options: [.allowFragments]) as? [String: Any]
                guard let result = (json?["results"] as? [Any])?.first as? [String: Any], let version = result["version"] as? String else {
                    throw VersionError.invalidResponse
                } // ์•ฑ์Šคํ† ์–ด ๋ฒ„์ „ ๊ฐ€์ ธ์˜ค๊ธฐ
                let needUpdate = currentVersion.compare(version,options: .numeric) == .orderedAscending
                completion(needUpdate, nil)
                // true is needUpdate
                // false is latest version
            } catch {
                completion(nil, error)
            }
        }
        task.resume()
        return task
    }
    
    // AppStore ์ด๋™
   static func appUpdate() {
        let appId = "~~~~"        // ์•ฑ ์Šคํ† ์–ด์— ์ผ๋ฐ˜ ์ •๋ณด์˜ Apple ID ์ž…๋ ฅ
        // UIApplication ์€ Main Thread ์—์„œ ์ฒ˜๋ฆฌ
        DispatchQueue.main.async {
            if let url = URL(string: "https://apps.apple.com/kr/app/\(appId)"), UIApplication.shared.canOpenURL(url) {
                if #available(iOS 10.0, *) {
                    UIApplication.shared.open(url, options: [:], completionHandler: {_ in
                        UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                            exit(0)
                        }
                    })
                } else {
                    UIApplication.shared.openURL(url)
                }
            }
        }
    }
}

 

์—…๋ฐ์ดํŠธ ์—ฌ๋ถ€ ํ™•์ธํ•˜๋Š” ์ฝ”๋“œ์™€ ์•ฑ์Šคํ† ์–ด๋กœ ์ด๋™ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

 

 

๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜๋Š” ์‚ฌ์šฉ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค

 

func checkVersionTask() {
        _ = try? AppVersionCheck.isUpdateAvailable { [weak self] (update, error) in
            guard let self = self else { return }
            if let error = error {
                debugPrint("checkVersionTask err : \(error)")
                return
            } else if let update = update {
                if update {
                    debugPrint("This App is old version")
                    DispatchQueue.main.async {
                        let alert = UIAlertController(title: "์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค", message: "", preferredStyle: UIAlertController.Style.alert)
                        let okAction = UIAlertAction(title: "ํ™•์ธ", style: .default, handler : { _ in
                            AppVersionCheck.appUpdate()
                        })
                        alert.addAction(okAction)
                        self.present(alert, animated: true, completion: nil)
                    }
                    return
                } else {
                    debugPrint("This App is latest version")
                    // self.loginLogic()
                    return
                }
            }
        }
    }

 

 

old version ์ผ ๊ฒฝ์šฐ

Alert์„ ๋„์šฐ๊ณ  ํ™•์ธ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๊ฒฝ์šฐ appstore๋กœ ๋ณด๋‚ด๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

latest version ์ผ ๊ฒฝ์šฐ

์ž‘์„ฑํ•œ loginLogic()์ด ๋™์ž‘ํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

 

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๋Œ“๊ธ€