[Swift] 강제 업데이트 Alert 설정

chaentopia·2023년 8월 21일
0


프로젝트 작업 중 아찔한 이슈를 발견했었다... 그러나 이미 배포된 상태...
지금이야 괜찮지만 나중에 유저가 많아지게 된다면 아찔에 아찔에 아찔을 더해서..
때문에 강제 업데이트 알럿을 설정해주기로 했다. 그 전에, 앱스토어에 올라갈 앱이 App Store Connect에 등록이 되어 있어야 하고, AppID를 알고 있어야만 해당 사항을 처리할 수 있다.

우선 버전 체크를 위해서 AppStoreCheck.swift 파일을 만들어주었다.

//  AppStoreCheck.swift

import UIKit

class AppStoreCheck {
    
    // 앱 자체의 버전 정보를 확인한다.
    static let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
    
    // 앱스토어 링크
    static let appStoreOpenUrlString = "itms-apps://itunes.apple.com/app/apple-store/(여기에AppID)"
    
    // 앱스토어에 올라와있는 버전 정보
    func latestVersion() -> String? {
        let appleID = "(여기에AppID)"
        guard let url = URL(string: "http://itunes.apple.com/lookup?id=\(appleID)&country=kr"),
              let data = try? Data(contentsOf: url),
              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 else {
            return nil
        }
        return appStoreVersion
    }
    
    // 앱스토어로 이동
    func openAppStore() {
        guard let url = URL(string: AppStoreCheck.appStoreOpenUrlString) else { return }
        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }
    }
}
  • appVersion : 앱 자체의 버전 정보를 확인한다.
  • appStoreOpenUrlString: 앱 스토어 링크
  • latestVersion: 앱스토어에 올라와있는 버전 정보를 받아오는 함수
  • openAppStore: 앱스토어로 이동하는 함수

이렇게 구성을 해주었다.
원래는 해당 내용을 스플래시 화면에서 진입 전에 띄워주려고 하였으나, 스플래시 화면이 빠르게 사라진다는 이슈를 발견하였고, 서비스 특성 상 경우에 따라 rootViewController가 다양하게 달라지기 때문에 ViewController에서 설정하는 것이 어려웠다.
또한 백그라운드에서 포그라운드로 진입 시에도 버전을 체크하여 업데이트 알럿을 띄워야 했기 때문에 SceneDelegate에서 설정해주었다.

//  SceneDelegate.swift
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
    var window: UIWindow?
    ...
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    	guard let windowScene = (scene as? UIWindowScene) else { return }
        self.window = UIWindow(windowScene: windowScene)
        ...
        let viewController = ViewController()
        window?.rootViewController = viewController
        
        self.window?.makeKeyAndVisible()
        self.checkAndUpdateIfNeeded() //모든 makeKeyAndVisible뒤에 설정
        ...
	}
    
    // 백그라운드에서 포그라운드가 될 때 거치는 함수에도 넣어줌
    func sceneWillEnterForeground(_ scene: UIScene) {
        checkAndUpdateIfNeeded()
    }
    ...
    
    // 업데이트가 필요한지 확인하는 함수
    func checkAndUpdateIfNeeded() {
    	// 현재 앱스토어에 있는 버전
        let marketingVersion = AppStoreCheck().latestVersion() ?? ""
        
        // 현재 프로젝트의 버전
        let currentProjectVersion = AppStoreCheck.appVersion ?? ""
        
        // 앱스토어에 있는 버전을 .마다 나눈 것 (예: 1.2.1 버전이라면 [1, 2, 1])
        let splitMarketingVersion = marketingVersion.split(separator: ".").map { $0 }
        
        // 현재 프로젝트 버전을 .마다 나눈 것 
        let splitCurrentProjectVersion = currentProjectVersion.split(separator: ".").map { $0 }
        
        // [Major].[Minor].[Patch] 중 [Major]을 비교하여 앱스토어에 있는 버전이 높을 경우 알럿 띄우기
        if splitCurrentProjectVersion[0] < splitMarketingVersion[0] {
            showUpdateAlert(version: marketingVersion)
            
        // [Major].[Minor].[Patch] 중 [Minor]을 비교하여 앱스토어에 있는 버전이 높을 경우 알럿 띄우기
        } else if splitCurrentProjectVersion[1] < splitMarketingVersion[1] {
            showUpdateAlert(version: marketingVersion)
            
        // 나머지 상황에서는 업데이트 알럿을 띄우지 않음
        } else {
            print("현재 최신 버젼입니다.")
        }
    }
    
    // 알럿을 띄우는 함수
    func showUpdateAlert(version: String) {
        let alert = UIAlertController(
            title: "업데이트 알림",
            message: "\(version)으로의 업데이트 사항이 있습니다. 앱스토어에서 앱을 업데이트 해주세요.",
            preferredStyle: .alert
        )
        
        // 업데이트 버튼을 누르면 앱스토어로 이동
        let updateAction = UIAlertAction(title: "업데이트", style: .default) { _ in
            AppStoreCheck().openAppStore()
        }
        
        alert.addAction(updateAction)
        window?.rootViewController?.present(alert, animated: true, completion: nil)
    }
}

이렇게 Major와 Minor이 차이가 날 때만 처리를 해주었다. 때문에 강제 업데이트 관련하여 컨벤션과 어떤 경우에 강제 업데이트를 시킬 것인지 정하는 것도 중요할 것 같다~!!

이렇게 하면 백그라운드 -> 포그라운드 진입 시에도 업데이트가 필요하다면 알럿을 띄우기 때문에 업데이트를 하지 않고 앱을 사용할 수 없게 된다. 이 부분까지 신경써줘야 하는 게 개발자의 할 일인 것 같다... 파이팅

profile
the pale blue dot

0개의 댓글