[SWIFT] [IOS] Implémentez le mécanisme de mise à jour semi-forcée en passant

introduction

Dans cet article, nous allons vous montrer comment implémenter ** un mécanisme qui indique à l'utilisateur qu'une nouvelle version a été publiée au lancement de l'application et invite à une mise à jour (appelée mise à jour semi-forcée dans cet article) **.

La mise à jour forcée est un mécanisme que vous voyez souvent dans les applications de jeu. En rendant l'application indisponible jusqu'à ce que vous la mettiez à jour, vous pouvez toujours l'exécuter avec la dernière version. Cependant, il n'est pas pratique de ne pas pouvoir l'utiliser lorsque vous souhaitez l'utiliser immédiatement car vous n'êtes pas toujours dans un environnement de communication où les utilisateurs peuvent se mettre à jour. Du point de vue d'une telle convivialité, j'aime la semi-force que j'ai gardée avant de provoquer la mise à jour.

À propos, s'il y a une divergence dans la version de l'application installée par l'utilisateur, il sera difficile de modifier la fonction existante et de ne pas pouvoir fournir la dernière fonction. Par exemple, lors de la migration d'une base de données pour plusieurs générations, je marche parfois sur un bogue inattendu que la version vole.

Il est souhaitable que les utilisateurs utilisent toujours la dernière version, et je pense qu'il vaut mieux adopter activement un mécanisme pour encourager les mises à jour.

Implémentation à l'aide de l'API de recherche iTunes

Lors de l'implémentation du mécanisme de mise à jour semi-forcée, le flux suivant peut être pris en compte.

No Title.png

  1. Demandez au serveur la dernière version lorsque l'application est lancée
  2. Comparez la version renvoyée par le serveur avec la version actuelle
  3. Affichez une interface utilisateur qui invite l'utilisateur à mettre à niveau s'il ne s'agit pas de la dernière

iTunes Search API

Vous pouvez préparer votre propre serveur pour renvoyer la dernière version, mais ici [API de recherche iTunes](https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search- Utilisez api /). Grâce à cette API, vous pouvez obtenir gratuitement des informations sur les applications distribuées dans l'App Store. Les informations sur l'application incluent également les informations de version publiées sur l'App Store.

En utilisant l'API de recherche iTunes, ** les informations de version de l'application qui peuvent être obtenues seront automatiquement mises à jour lorsque l'application est effectivement livrée depuis l'App Store **, de sorte que la version de livraison sera livrée par vous-même. Il est facile à utiliser car il n'est pas nécessaire de configurer un serveur pour gérer les données et vous n'oublierez pas de mettre à jour la dernière version.

Classe AppStore

J'ai implémenté une classe AppStore qui atteint l'API de recherche iTunes ci-dessous. (J'utilise Alamofire v5 pour la bibliothèque de communication)

import Foundation
import Alamofire

typealias LookUpResult = [String: Any]

enum AppStoreError: Error {
    case networkError
    case invalidResponseData
}

class AppStore {

    private static let lastCheckVersionDateKey = "\(Bundle.main.bundleIdentifier!).lastCheckVersionDateKey"

    static func checkVersion(completion: @escaping (_ isOlder: Bool) -> Void) {
        let lastDate = UserDefaults.standard.integer(forKey: lastCheckVersionDateKey)
        let now = currentDate

        //Passer jusqu'au changement de date
        guard lastDate < now else { return }

        UserDefaults.standard.set(now, forKey: lastCheckVersionDateKey)

        lookUp { (result: Result<LookUpResult, AppStoreError>) in
            do {
                let lookUpResult = try result.get()

                if let storeVersion = lookUpResult["version"] as? String {
                    let storeVerInt = versionToInt(storeVersion)
                    let currentVerInt = versionToInt(Bundle.version)
                    completion(storeVerInt > currentVerInt)
                }
            }
            catch {
                completion(false)
            }
        }
    }

    static func versionToInt(_ ver: String) -> Int {
        let arr = ver.split(separator: ".").map { Int($0) ?? 0 }

        switch arr.count {
            case 3:
                return arr[0] * 1000 * 1000 + arr[1] * 1000 + arr[2]
            case 2:
                return arr[0] * 1000 * 1000 + arr[1] * 1000
            case 1:
                return arr[0] * 1000 * 1000
            default:
                assertionFailure("Illegal version string.")
                return 0
        }
    }

    ///Ouvrez l'App Store
    static func open() {
        if let url = URL(string: storeURLString), UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url)
        }
    }
}

private extension AppStore {

    static var iTunesID: String {
        "<YOUR_ITUNES_ID>"
    }

    ///Page de l'App Store
    static var storeURLString: String {
        "https://apps.apple.com/jp/app/XXXXXXX/id" + iTunesID
    }

    /// iTunes Search API
    static var lookUpURLString: String {
        "https://itunes.apple.com/lookup?id=" + iTunesID
    }

    ///Renvoie un entier tel que 20201116 généré à partir de la date et de l'heure actuelles
    static var currentDate: Int {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .gregorian)
        formatter.locale = .current
        formatter.dateFormat = "yyyyMMdd"
        return Int(formatter.string(from: Date()))!
    }

    static func lookUp(completion: @escaping (Result<LookUpResult, AppStoreError>) -> Void) {
        AF.request(lookUpURLString).responseJSON(queue: .main, options: .allowFragments) { (response: AFDataResponse<Any>) in
            let result: Result<LookUpResult, AppStoreError>

            if let error = response.error {
                result = .failure(.networkError)
            }
            else {
                if let value = response.value as? [String: Any],
                   let results = value["results"] as? [LookUpResult],
                   let obj = results.first {
                    result = .success(obj)
                }
                else {
                    result = .failure(.invalidResponseData)
                }
            }

            completion(result)
        }
    }
}

extension Bundle {
    /// Info.Obtenez le numéro de version dans plist. Majeur.minor.On suppose qu'il est au format patch
    static var version: String {
        return Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
    }
}

Remplacez «<YOUR_ITUNES_ID>» par l'ID iTunes de l'application pour laquelle vous souhaitez obtenir des informations de version. L'identifiant iTunes s'affiche dans l'URL lorsque vous ouvrez la page de l'application sur l'App Store dans votre navigateur. De même, remplacez storeURLString par l'URL de l'App Store.

Slice.png

Dans l'implémentation ci-dessus, la version est vérifiée pour les mises à jour une fois par jour. La comparaison de version est basée sur la chaîne de version au format * major.minor.patch * divisée par des points et convertie en type Int (voir la méthode versionToInt (_:)). Avec la méthode ci-dessus, mineur et patch ne peuvent prendre que 1000 pas de 0 à 999, mais cela devrait suffire.

Lorsque vous utilisez la classe AppStore, créez la méthode suivante dans ViewController et appelez viewDidAppear ou UIApplication.willEnterForegroundNotification avec la méthode observée.

private extension ViewController {

    func checkVersion() {
        AppStore.checkVersion { (isOlder: Bool) in
            guard isOlder else { return }

            let alertController = UIAlertController(title: "Il y a une nouvelle version!", message: "Veuillez mettre à jour.", preferredStyle: .alert)
            alertController.addAction(UIAlertAction(title: "mise à jour", style: .default) { action in
                AppStore.open()
            })
            alertController.addAction(UIAlertAction(title: "Annuler", style: .cancel))
            self.present(alertController, animated: true)
        }
    }
}

Avec l'implémentation ci-dessus, il est désormais possible d'informer l'utilisateur qu'une nouvelle version a été publiée.

Recommended Posts

[IOS] Implémentez le mécanisme de mise à jour semi-forcée en passant
Implémentez iOS14 UICollectionView avec le code minimum requis.