func appUpdateAvailable(storeInfoURL: String) -> Bool
{
var upgradeAvailable = false
// Get the main bundle of the app so that we can determine the app's version number
let bundle = NSBundle.mainBundle()
if let infoDictionary = bundle.infoDictionary {
// The URL for this app on the iTunes store uses the Apple ID for the This never changes, so it is a constant
let urlOnAppStore = NSURL(string: storeInfoURL)
if let dataInJSON = NSData(contentsOfURL: urlOnAppStore!) {
// Try to deserialize the JSON that we got
if let lookupResults = try? NSJSONSerialization.JSONObjectWithData(dataInJSON, options: NSJSONReadingOptions()) {
// Determine how many results we got. There should be exactly one, but will be zero if the URL was wrong
if let resultCount = lookupResults["resultCount"] as? Int {
if resultCount == 1 {
// Get the version number of the version in the App Store
if let appStoreVersion = lookupResults["results"]!![0]["version"] as? String {
// Get the version number of the current version
if let currentVersion = infoDictionary["CFBundleShortVersionString"] as? String {
// Check if they are the same. If not, an upgrade is available.
if appStoreVersion != currentVersion {
upgradeAvailable = true
}
}
}
}
}
}
}
}
return upgradeAvailable
}
func appUpdateAvailable() -> Bool
{
let storeInfoURL: String = "http://itunes.apple.com/lookup?bundleId=YOURBUNDLEID"
var upgradeAvailable = false
// Get the main bundle of the app so that we can determine the app's version number
let bundle = NSBundle.mainBundle()
if let infoDictionary = bundle.infoDictionary {
// The URL for this app on the iTunes store uses the Apple ID for the This never changes, so it is a constant
let urlOnAppStore = NSURL(string: storeInfoURL)
if let dataInJSON = NSData(contentsOfURL: urlOnAppStore!) {
// Try to deserialize the JSON that we got
if let dict: NSDictionary = try? NSJSONSerialization.JSONObjectWithData(dataInJSON, options: NSJSONReadingOptions.AllowFragments) as! [String: AnyObject] {
if let results:NSArray = dict["results"] as? NSArray {
if let version = results[0].valueForKey("version") as? String {
// Get the version number of the current version installed on device
if let currentVersion = infoDictionary["CFBundleShortVersionString"] as? String {
// Check if they are the same. If not, an upgrade is available.
print("\(version)")
if version != currentVersion {
upgradeAvailable = true
}
}
}
}
}
}
}
return upgradeAvailable
}
class func appStoreAppVersion() -> String?
{
guard let bundleInfo = NSBundle.mainBundle().infoDictionary else {
dlog_Error("Counldn't fetch bundleInfo.")
return nil
}
let bundleId = bundleInfo[kCFBundleIdentifierKey as String] as! String
// dbug__print("bundleId = \(bundleId)")
let address = "http://itunes.apple.com/lookup?bundleId=\(bundleId)"
// dbug__print("address = \(address)")
guard let url = NSURLComponents.init(string: address)?.URL else {
dlog_Error("Malformed internet address: \(address)")
return nil
}
guard let data = NSData.init(contentsOfURL: url) else {
if Util.isInternetAvailable() {
dlog_MajorWarning("Web server request failed. Yet internet is reachable. Url was: \(address)")
}// else: internet is unreachable. All ok. It is of course impossible to fetch the appStoreAppVersion like this.
return nil
}
// dbug__print("data.length = \(data.length)")
if data.length < 100 { //: We got 42 for a wrong address. And aproximately 4684 for a good response
dlog_MajorWarning("Web server message is unexpectedly short: \(data.length) bytes")
}
guard let response = try? NSJSONSerialization.JSONObjectWithData(data, options: []) else {
dlog_Error("Failed to parse server response.")
return nil
}
guard let responseDic = response as? [String: AnyObject] else {
dlog_Error("Not a dictionary keyed with strings. Response with unexpected format.")
return nil
}
guard let resultCount = responseDic["resultCount"] else {
dlog_Error("No resultCount found.")
return nil
}
guard let count = resultCount as? Int else { //: Swift will handle NSNumber.integerValue
dlog_Error("Server response resultCount is not an NSNumber.integer.")
return nil
}
//:~ Determine how many results we got. There should be exactly one, but will be zero if the URL was wrong
guard count == 1 else {
dlog_Error("Server response resultCount=\(count), but was expected to be 1. URL (\(address)) must be wrong or something.")
return nil
}
guard let rawResults = responseDic["results"] else {
dlog_Error("Response does not contain a field called results. Results with unexpected format.")
return nil
}
guard let resultsArray = rawResults as? [AnyObject] else {
dlog_Error("Not an array of results. Results with unexpected format.")
return nil
}
guard let resultsDic = resultsArray[0] as? [String: AnyObject] else {
dlog_Error("Not a dictionary keyed with strings. Results with unexpected format.")
return nil
}
guard let rawVersion = resultsDic["version"] else {
dlog_Error("The key version is not part of the results")
return nil
}
guard let versionStr = rawVersion as? String else {
dlog_Error("Version is not a String")
return nil
}
return versionStr.e_trimmed()
}
extension String {
func e_trimmed() -> String
{
return stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}
}
function isUpdateAvailable_iOS (data) {
var storeVersion = data.version;
var releaseNotes = data.releaseNotes;
// Check store Version Against My App Version ('1.14.3' -> 1143)
var _storeV = parseInt(storeVersion.replace(/\./g, ''));
var _appV = parseInt(appVersion.substring(1).replace(/\./g, ''));
$('#ft-main-menu-btn').off();
if (_storeV > _appV) {
// Update Available
$('#ft-main-menu-btn').text('Update Available');
$('#ft-main-menu-btn').click(function () {
// Open Store
window.open('https://itunes.apple.com/us/app/appname/idUniqueID', '_system');
});
} else {
$('#ft-main-menu-btn').html(' ');
// Release Notes
settings.updateReleaseNotes('v' + storeVersion, releaseNotes);
}
}
import Alamofire
class VersionCheck {
public static let shared = VersionCheck()
func isUpdateAvailable(callback: @escaping (Bool)->Void) {
let bundleId = Bundle.main.infoDictionary!["CFBundleIdentifier"] as! String
Alamofire.request("https://itunes.apple.com/lookup?bundleId=\(bundleId)").responseJSON { response in
if let json = response.result.value as? NSDictionary, let results = json["results"] as? NSArray, let entry = results.firstObject as? NSDictionary, let versionStore = entry["version"] as? String, let versionLocal = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
let arrayStore = versionStore.split(separator: ".").compactMap { Int($0) }
let arrayLocal = versionLocal.split(separator: ".").compactMap { Int($0) }
if arrayLocal.count != arrayStore.count {
callback(true) // different versioning system
return
}
// check each segment of the version
for (localSegment, storeSegment) in zip(arrayLocal, arrayStore) {
if localSegment < storeSegment {
callback(true)
return
}
}
}
callback(false) // no new version or failed to fetch app store version
}
}
}
然后使用它:
VersionCheck.shared.isUpdateAvailable() { hasUpdates in
print("is update available: \(hasUpdates)")
}
func showAppStoreVersionUpdateAlert(isForceUpdate: Bool) {
do {
//Get Bundle Identifire from Info.plist
guard let bundleIdentifire = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String else {
print("No Bundle Info found.")
throw CustomError.invalidIdentifires
}
// Build App Store URL
guard let url = URL(string:"http://itunes.apple.com/lookup?bundleId=" + bundleIdentifire) else {
print("Isse with generating URL.")
throw CustomError.invalidURL
}
let serviceTask = URLSession.shared.dataTask(with: url) { (responseData, response, error) in
do {
// Check error
if let error = error { throw error }
//Parse response
guard let data = responseData else { throw CustomError.jsonReading }
let result = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
let itunes = ItunesAppInfoItunes.init(fromDictionary: result as! [String : Any])
print(itunes.results)
if let itunesResult = itunes.results.first {
print("App Store Varsion: ",itunesResult.version)
//Get Bundle Version from Info.plist
guard let appShortVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
print("No Short Version Info found.")
throw CustomError.invalidVersion
}
if appShortVersion == itunesResult.version {
//App Store & Local App Have same Version.
print("Same Version at both side")
} else {
//Show Update alert
var message = ""
//Get Bundle Version from Info.plist
if let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String {
message = "\(appName) has new version(\(itunesResult.version!)) available on App Store."
} else {
message = "This app has new version(\(itunesResult.version!)) available on App Store."
}
//Show Alert on the main thread
DispatchQueue.main.async {
self.showUpdateAlert(message: message, appStoreURL: itunesResult.trackViewUrl, isForceUpdate: isForceUpdate)
}
}
}
} catch {
print(error)
}
}
serviceTask.resume()
} catch {
print(error)
}
}
打开 AppStore URL 的警报功能:
func showUpdateAlert(message : String, appStoreURL: String, isForceUpdate: Bool) {
let controller = UIAlertController(title: "New Version", message: message, preferredStyle: .alert)
//Optional Button
if !isForceUpdate {
controller.addAction(UIAlertAction(title: "Later", style: .cancel, handler: { (_) in }))
}
controller.addAction(UIAlertAction(title: "Update", style: .default, handler: { (_) in
guard let url = URL(string: appStoreURL) else {
return
}
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
}))
let applicationDelegate = UIApplication.shared.delegate as? AppDelegate
applicationDelegate?.window?.rootViewController?.present(controller, animated: true)
}
import Alamofire
class VersionCheck {
public static let shared = VersionCheck()
func isUpdateAvailable(callback: @escaping (Bool)->Void) {
let bundleId = Bundle.main.infoDictionary!["CFBundleIdentifier"] as! String
Alamofire.request("https://itunes.apple.com/lookup?bundleId=\(bundleId)").responseJSON { response in
if let json = response.result.value as? NSDictionary, let results = json["results"] as? NSArray, let entry = results.firstObject as? NSDictionary, let versionStore = entry["version"] as? String, let versionLocal = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
let arrayStore = versionStore.split(separator: ".")
let arrayLocal = versionLocal.split(separator: ".")
if arrayLocal.count != arrayStore.count {
callback(true) // different versioning system
return
}
// check each segment of the version
for (key, value) in arrayLocal.enumerated() {
if Int(value)! < Int(arrayStore[key])! {
callback(true)
return
} else if Int(value)! > Int(arrayStore[key])! {
callback(false)
return
}
}
}
callback(false) // no new version or failed to fetch app store version
return
}
}
}
用法总是相同的:
VersionCheck.shared.isUpdateAvailable() { hasUpdates in
print("is update available: \(hasUpdates)")
}
var currVer = "1.2.0";
var newVer = "1.2.1";
var arr1 = currVer.split(".");
var arr2 = newVer.split(".");
var intArray1 = arr1.map(function(txt){return (txt.length===0?0:parseInt(txt));});
var intArray2 = arr2.map(function(txt){return (txt.length===0?0:parseInt(txt));});
var l1 = intArray1.length;
var l2 = intArray2.length;
var isOutdated=false;
if(l1>0){
if(l2>0){
// compare both currentversion and new version is not empty
if(l1==l2){
for(i=0;i<l1;i++){
if(intArray2[i]>intArray1[i]){
// tag as outdated if matched digit of newVersion is greater than the matching digit of current version
isOutdated=true;
break;
}
}
}
else{
if((l2-l1)>0){
for(i=0;i<(l2-l1);i++){
intArray1.push(0);
}
}
if((l1-l2)>0){
for(i=0;i<(l1-l2);i++){
intArray2.push(0);
}
}
l1 = intArray1.length;
l2 = intArray2.length;
for(i=0;i<l1;i++){
if(intArray2[i]>intArray1[i]){
// tag as outdated if matched digit of newVersion is greater than the matching digit of current version
isOutdated=true;
break;
}
}
}
}
else{
// if there's no new version, tag as not outdated
isOutdated = false;
}
}
else{
// if current version is empty, tag as not outdated
isOutdated = false;
}
document.getElementById("versionTxt").innerHTML = currVer + " -> " + JSON.stringify(intArray1);
document.getElementById("versionTxt2").innerHTML = newVer + " -> " + JSON.stringify(intArray2);
document.getElementById("isOutdatedTxt").innerHTML = "Outdated? " + isOutdated.toString();
#import Up2Dater
let updater = Up2Dater()
updater.isNewVersionAvailable { result in
switch result {
case.success(let model):
// if the model is nil, there's no new version
print(model?.version, model?.releaseNotes, model?.appStorePath)
case .failure(let error):
print(error.description)
}
}
比较字符串版本比使用关系运算子(如 <或 >=)更好(例如“3.1.7”< “3.1.10”)
func isNewer(_ version: String,
then bundleVersion: String) -> Bool {
switch version.compare(bundleVersion, options: .numeric) {
case .orderedSame,
.orderedAscending:
return false
case .orderedDescending:
return true
}
}