174 Stimmen

Prüfen, ob meine App eine neue Version im AppStore hat

Ich möchte manuell prüfen, ob es neue Updates für meine App gibt, während der Benutzer sich in ihr befindet, und ihn auffordern, die neue Version herunterzuladen. Kann ich dies tun, indem ich die Version meiner App im App Store - programmatisch - überprüfe?

5voto

Sandu Punkte 438

FÜR SWIFT 4 und 3.2:

Zuerst müssen wir die Bundle-ID aus dem Bundle-Info-Dictionary holen und isUpdaet auf false setzen.

    var isUpdate = false
    guard let bundleInfo = Bundle.main.infoDictionary,
        let currentVersion = bundleInfo["CFBundleShortVersionString"] as? String,
        //let identifier = bundleInfo["CFBundleIdentifier"] as? String,
        let url = URL(string: "http://itunes.apple.com/lookup?bundleId=\(identifier)")
        else{
        print("something wrong")
            completion(false)
        return
       }

Dann müssen wir einen urlSession-Aufruf aufrufen, um die Version von itunes zu erhalten.

    let task = URLSession.shared.dataTask(with: url) {
        (data, resopnse, error) in
        if error != nil{
             completion(false)
            print("something went wrong")
        }else{
            do{
                guard let reponseJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any],
                let result = (reponseJson["results"] as? [Any])?.first as? [String: Any],
                let version = result["version"] as? String
                else{
                     completion(false)
                    return
                }
                print("Current Ver:\(currentVersion)")
                print("Prev version:\(version)")
                if currentVersion != version{
                    completion(true)
                }else{
                    completion(false)
                }
            }
            catch{
                 completion(false)
                print("Something went wrong")
            }
        }
    }
    task.resume()

DER VOLLSTÄNDIGE CODE WIRD WIE FOLGT AUSSEHEN:

func checkForUpdate(completion:@escaping(Bool)->()){

    guard let bundleInfo = Bundle.main.infoDictionary,
        let currentVersion = bundleInfo["CFBundleShortVersionString"] as? String,
        //let identifier = bundleInfo["CFBundleIdentifier"] as? String,
        let url = URL(string: "http://itunes.apple.com/lookup?bundleId=\(identifier)")
        else{
        print("some thing wrong")
            completion(false)
        return
       }

    let task = URLSession.shared.dataTask(with: url) {
        (data, resopnse, error) in
        if error != nil{
             completion(false)
            print("something went wrong")
        }else{
            do{
                guard let reponseJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any],
                let result = (reponseJson["results"] as? [Any])?.first as? [String: Any],
                let version = result["version"] as? String
                else{
                     completion(false)
                    return
                }
                print("Current Ver:\(currentVersion)")
                print("Prev version:\(version)")
                if currentVersion != version{
                    completion(true)
                }else{
                    completion(false)
                }
            }
            catch{
                 completion(false)
                print("Something went wrong")
            }
        }
    }
    task.resume()
}

Dann können wir die Funktion beliebig oft aufrufen.

    checkForUpdate { (isUpdate) in
        print("Update needed:\(isUpdate)")
        if isUpdate{
            DispatchQueue.main.async {
                print("new update Available")
            }
        }
    }

5voto

juanjo Punkte 3517

Mauersegler 4

Wir können die neue JSONDecoder zum Parsen der Antwort von itunes.apple.com/lookup und repräsentieren sie mit Decodable-Klassen oder Structs:

class LookupResult: Decodable {
    var results: [AppInfo]
}

class AppInfo: Decodable {
    var version: String
}

Wir können auch andere Eigenschaften hinzufügen zu AppInfo für den Fall, dass wir die releaseNotes oder eine andere Eigenschaft.

Jetzt können wir eine asynchrone Anfrage stellen mit URLSession :

func getAppInfo(completion: @escaping (AppInfo?, Error?) -> Void) -> URLSessionDataTask? {
    guard let identifier = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String,
          let url = URL(string: "http://itunes.apple.com/lookup?bundleId=\(identifier)") else {
            DispatchQueue.main.async {
                completion(nil, VersionError.invalidBundleInfo)
            }
            return nil
    }
    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 result = try JSONDecoder().decode(LookupResult.self, from: data)
            guard let info = result.results.first else { throw VersionError.invalidResponse }

            completion(info, nil)
        } catch {
            completion(nil, error)
        }
    }
    task.resume()
    return task
}

enum VersionError: Error {
    case invalidBundleInfo, invalidResponse
}

Diese Funktion empfängt einen Abschluss, der aufgerufen wird, wenn die Anfrage abgeschlossen ist, und gibt ein URLSessionDataTask für den Fall, dass wir die Anfrage abbrechen müssen, und kann wie folgt aufgerufen werden:

func checkVersion() {
    let info = Bundle.main.infoDictionary
    let currentVersion = info?["CFBundleShortVersionString"] as? String
    _ = getAppInfo { (info, error) in
        if let error = error {
            print(error)
        } else if info?.version == currentVersion {
            print("updated")
        } else {
            print("needs update")
        }
    }
}

0 Stimmen

Wo haben Sie diesen Code eingefügt? Ich sehe, dass Sie LookupResult und AppInfo auf decodierbar setzen, aber ich sehe sie nirgends gespeichert. Was übersehe ich hier?

0 Stimmen

Sie deklarieren die LookupResult y AppInfo Klassen irgendwo in Ihrem Projekt, vorzugsweise in einer separaten Datei: Sie werden verwendet, wenn Sie die Antwort dekodieren: JSONDecoder().decode(LookupResult.self, from: data) und sie enthalten die Versionszeichenfolge

0 Stimmen

Basierend auf Ihrer Antwort erstelle ich eine Datei unter Verwendung Ihres Codes Bitte überprüfen Sie, dass iOS-Swift-ArgAppUpdater

4voto

moonvader Punkte 17469

Diese Frage wurde 2011 gestellt, ich habe sie 2018 gefunden, als ich nach einer Möglichkeit suchte, nicht nur die neue Version einer App im App Store zu prüfen, sondern auch den Nutzer darüber zu informieren.

Nach einer kleinen Recherche bin ich zu dem Schluss gekommen, dass Antwort von juanjo (bezogen auf Swift 3) https://stackoverflow.com/a/40939740/1218405 ist die optimale Lösung, wenn Sie dies im Code selbst tun wollen

Ich kann auch zwei großartige Projekte auf GitHub empfehlen (jeweils 2300+ Sterne)

Beispiel für Sirene (AppDelegate.swift)

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

      let siren = Siren.shared
      siren.checkVersion(checkType: .immediately)

      return true
    }
  • Sie können auch verschiedene Arten von Warnungen über neue Versionen anzeigen (die es erlauben, die Version zu überspringen oder den Benutzer zur Aktualisierung zu zwingen)
  • Sie können festlegen, wie oft die Versionsprüfung stattfinden soll (täglich / wöchentlich / sofort)
  • Sie können festlegen, wie viele Tage nach der Veröffentlichung einer neuen Version im App-Store eine Warnung erscheinen soll

0 Stimmen

Links zu einer bestehenden Antwort sind keine Antworten. Außerdem sind Links zu Bibliotheken ebenfalls keine Antworten, es sei denn, Sie fügen Ihrer Antwort ausdrücklich hinzu, wie der Link die Frage beantwortet (fügen Sie Codebeispiele hinzu usw.).

4voto

uliwitness Punkte 8124

Warnung: Die meisten der gegebenen Antworten rufen die URL synchron ab (mit -dataWithContentsOfURL: o -sendSynchronousRequest: . Das ist schlecht, denn es bedeutet, dass Ihre Anwendung mehrere Minuten lang nicht reagiert, wenn die Mobilfunkverbindung während der Abfrage abbricht. jamais den Internetzugang synchron auf dem Hauptthread durchführen.

Die richtige Antwort ist die Verwendung einer asynchronen API:

    NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString* appID = infoDictionary[@"CFBundleIdentifier"];
    NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
    NSURLSession         *  session = [NSURLSession sharedSession];
    NSURLSessionDataTask *  theTask = [session dataTaskWithRequest: [NSURLRequest requestWithURL: url] completionHandler:
    ^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
    {
        NSDictionary<NSString*,NSArray*>* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        if ([lookup[@"resultCount"] integerValue] == 1)
        {
            NSString* appStoreVersion = lookup[@"results"].firstObject[@"version"];
           NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];

            if ([appStoreVersion compare:currentVersion options:NSNumericSearch] == NSOrderedDescending) {
                // *** Present alert about updating to user ***
            }
        }
    }];
    [theTask resume];

Die Standardzeitüberschreitung für Netzwerkverbindungen beträgt mehrere Minuten, und selbst wenn die Anfrage durchgeht, kann sie bei einer schlechten EDGE-Verbindung so langsam sein, dass sie so lange dauert. Sie wollen nicht, dass Ihre Anwendung in diesem Fall unbrauchbar ist. Um solche Dinge zu testen, ist es nützlich, Ihren Netzwerkcode mit Apples Network Link Conditioner auszuführen.

0 Stimmen

Danke, dass Sie diese Frage am Leben erhalten :-)

3voto

Lova Punkte 101
func isUpdateAvailable() -> Bool {
    guard
        let info = Bundle.main.infoDictionary,
        let identifier = info["CFBundleIdentifier"] as? String,
        let url = URL(string: "http://itunes.apple.com/lookup?bundleId=\(identifier)"),
        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]],
        results.count > 0,
        let versionString = results[0]["version"] as? String
        else {
            return false
    }

    return AppVersion(versionString) > AppVersion.marketingVersion
}

um den Versionsstring zu vergleichen:

https://github.com/eure/AppVersionMonitor

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X