배포된 앱을 업데이트 후 사용자 앱의 버전과 스토어의 앱 버전을 비교해서 업데이트 여부 얼럿 출력 및 스토어 바로가기 

 

import UIKit

enum VersionError: Error {
  case invalidResponse, invalidBundleInfo
}

/*
 사설 인증서 사용시 폐쇄망에서 ATS 통신오류시 예외처리
 */
extension StoreUpdateCheckWrapper: URLSessionDelegate {
    
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate) {
            completionHandler(.rejectProtectionSpace, nil)
        }
        if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
            let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
            completionHandler(.useCredential, credential)
        }
    }
}

class StoreUpdateCheckWrapper: NSObject {
    typealias StoreComplete = (Data?, URLResponse?, Error?) -> Void
    static let shared = StoreUpdateCheckWrapper()
    var session: URLSession?
    
    override init() {
        super.init()
        
        self.session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main)
    }
    
    //MARK: 업데이트 유무 확인
    static func updateStateCheck() {
        
        _ = try? StoreUpdateCheckWrapper.isUpdateAvailable { (storeVersion, trackViewUrl, error) in
            if let currentVersion = Bundle.appVersion(), let storeVersion = storeVersion {
                let arrayStore = storeVersion.split(separator: ".").compactMap { Int($0) }
                let arrayCurrent = currentVersion.split(separator: ".").compactMap { Int($0) }
                
                // check each segment of the version
                for (currentSegment, storeSegment) in zip(arrayCurrent, arrayStore) {
                    if currentSegment < storeSegment {
                        let appName = Bundle.appName()
                        
                        let alertTitle = "업데이트"
                        let alertMessage = "\(appName!) 최신버전 \(storeVersion)을 앱스토어에서 업데이트 하시겠습니까?"
                        
                        log(direction: .UI, ofType: self, datas: alertTitle, alertMessage)
                        
                        let alertController = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
                        
                        
                        let notNowButton = UIAlertAction(title: "다음에", style: .default)
                        alertController.addAction(notNowButton)
                        
                        
                        let updateButton = UIAlertAction(title: "업데이트", style: .default) { (action:UIAlertAction) in
                            
                            externalUrlOpen(externalUrl: trackViewUrl ?? "")
                            
                            UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                                exit(0)
                            }
                        }
                        
                        alertController.addAction(updateButton)
                        
                        DispatchQueue.main.async {
                            guard let topVC = UIApplication.currentTopViewController() else {
                                return
                            }
                            topVC.present(alertController, animated: true, completion: nil)
                        }
                        
                        return
                    }
                }
            }
        }
    }
    
    /// 스토어 최신버전 가져오기
    static func getStoreVersion(completion: @escaping (_ version: String) -> Void) {
        _ = try? StoreUpdateCheckWrapper.isUpdateAvailable { (storeVersion, trackViewUrl, error) in
            
            completion(storeVersion ?? "")
        }
        
    }
    
    static private func isUpdateAvailable(completion: @escaping (_ version: String?, _ storeUrl: String?, Error?) -> Void) throws -> URLSessionDataTask {
        // 앱 번들아이디 가져오기
         guard let identifier = Bundle.appBundleID(),
         let url = URL(string: "https://itunes.apple.com/kr/lookup?bundleId=\(identifier)") else {
         throw VersionError.invalidBundleInfo
         }
         
        // ATS 인증서 예외처리 로직                 
        let task = StoreUpdateCheckWrapper.shared.session?.dataTask(with: url) { (data, response, error) in

//        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,
                      let trackViewUrl = result["trackViewUrl"] as? String else {
                    throw VersionError.invalidResponse
                }
                
                DispatchQueue.main.async {
                    completion(version, trackViewUrl, nil)
                }
                
            } catch {
                DispatchQueue.main.async {
                    completion(nil, nil, error)
                }
            }
        }
        task?.resume()
        return task!
        
    }
}

 

사용방법

override func viewDidLoad() {
	super.viewDidLoad()
    
    // 스토어 업데이트 확인. 스토어 버전이 최신이면 얼럿창이 출력됨.
	StoreUpdateCheckWrapper.updateStateCheck()
}

+ Recent posts