[iOS] 현재 버전과 일치하지 않는 사용자를 앱스토어로 보내기

Jehyeon Lee·2023년 12월 15일
0

  • Issue

    • 앱스토어에 버전 업데이트가 된 버전을 설치하더라도 사용자들에게 업데이트가 완료되었다는 소식이 전달되지 않았습니다.
  • Problem

    • 사용자들은 이전 버전과 현재 버전이 둘 다 플레이 가능하여, 새로운 데이터가 있는 기능과 충돌이 발생하여 버그가 발생하였습니다.
  • Solution

    • 사용자가 앱을 처음 실행했을 때 현재 사용자의 앱 버전과 앱 스토어의 버전을 비교하여, 이전 버전이면 알림을 띄워 사용자에게 업데이트를 유도하도록 하였습니다.

일단 처음에 실행될 때 사용자가 실행하는 부분에서 버전을 체크할겁니다.

Appdelegate

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        VersionService.shared.loadAppStoreVersion { latestVersion in
            guard let latestVersion else { return }
            guard let nowVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else { return }
            let compareResult = nowVersion.compare(latestVersion, options: .numeric)
            switch compareResult {
            case .orderedAscending:
                VersionService.shared.isCheckVersion = true
            case .orderedDescending:
                VersionService.shared.isCheckVersion = false
            case .orderedSame:
                VersionService.shared.isCheckVersion = false
            }
        }

앱이 처음 시작할 때 VersionService에 현재 앱스토어의 버전을 확인하여 지금 버전과 맞는지 비교합니다
.orderedAscending 버전이 낮다는걸 의미합니다.
.orderedDescending 버전이 크다는걸 의미합니다.
- 버전이 큰건 의미없으니 false로둠 그럴 수 없기 떄문
.orderedSame 은 버전이 같다는걸 의미합니다.
이렇게 VersionService안에 isOldVersion를 Bool값으로 두어 값을 초기화 해줬습니다.

VersionService

//
//  VersionService.swift
//  Pico
//
//  Created by LJh on 12/16/23.
//
//
//  VersionService.swift
//  Pico
//
//  Created by LJh on 12/16/23.
//

import Foundation

final class VersionService {
    static let shared: VersionService = VersionService()
    
    var isOldVersion: Bool = false
    
    private let appleID = "appleID"
    private let bundleID = "bundleID"
    lazy var appStoreOpenUrlString = "itms-apps://itunes.apple.com/app/apple-store/\(appleID)"
    
    func loadAppStoreVersion(completion: @escaping (String?) -> Void) {
        let appStoreUrl = "http://itunes.apple.com/kr/lookup?bundleId=\(bundleID)"
        
        let task = URLSession.shared.dataTask(with: URL(string: appStoreUrl)!) { data, _, error in
            guard let data = data, error == nil else {
                completion(nil)
                return
            }
            
            do {
                if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any],
                   let results = json["results"] as? [[String: Any]],
                   let appStoreVersion = results[0]["version"] as? String {
                    completion(appStoreVersion)
                } else {
                    completion(nil)
                }
            } catch {
                completion(nil)
            }
        }
        task.resume()
    }
    
    func nowVersion() -> String {
        let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
        
        return version
    }
}

appleID와 BundleID를 서비스 안 번들 파일에 뒀습니다. (코드는 가림) func loadAppStoreVersion에서 JSON으로 저희 앱의 JSON을 가져와 그 안에

let results = json["results"] as? [[String: Any]],
                   let appStoreVersion = results[0]["version"] as? String {
                    completion(appStoreVersion)
                }

를 통해 버전만 가져옴으로써 앱스토어의 릴리즈된 앱의 버전을 확인할 수 있었습니다.

SignViewController

if !VersionService.shared.isOldVersion {
            showVersionAlert()
        } // viewDidLoad
        
private func showVersionAlert() {
        showCustomAlert(alertType: .onlyConfirm, titleText: "알림", messageText: "업데이트 이후에 사용이 가능합니다.", confirmButtonText: "확인", comfrimAction: {
            self.dismiss(animated: true, completion: {
                if let url = URL(string: VersionService.shared.appStoreOpenUrlString), UIApplication.shared.canOpenURL(url) {
                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
                    sleep(3)
                    exit(0)
                }
            })
        })
    }
    

굳이 VC에 한 이유는 알림은 AppDelegate 또는 SceneDelegate에서는 배치할 수 없기에 첫 시작 부분에 버전을 체크하도록 해뒀습니다.

SceneDelegate

if !VersionService.shared.isOldVersion {
            UserDefaultsManager.shared.removeAll()
        }

저희는 UserDefaults에 사용자의 정보가 있으면서 동시에 사용자가 일치하면 자동으로 로그인되는 기능이 있어서 UserDefaults의 모든 정보를 삭제함으로써 처음 버전을 체크하는 뷰로 이동합니다.

  • 결과 화면
profile
공부한거 느낌대로 써내려갑니당

0개의 댓글

관련 채용 정보