How to update ios6 enterprise apps over the air
Yes, it is possible. When you deploy an Enterprise application it requires a plist that contains metadata about the application. This metadata includes the version number that you can use to check for updates.
BOOL updateAvailable = NO;
NSDictionary *updateDictionary = [NSDictionary dictionaryWithContentsOfURL:
[NSURL URLWithString:@"http://www.example.com/pathToPlist"]];
if(updateDictionary)
{
NSArray *items = [updateDictionary objectForKey:@"items"];
NSDictionary *itemDict = [items lastObject];
NSDictionary *metaData = [itemDict objectForKey:@"metadata"];
NSString *newversion = [metaData valueForKey:@"bundle-version"];
NSString *currentversion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
updateAvailable = [newversion compare:currentversion options:NSNumericSearch] == NSOrderedDescending;
}
Once you detect the update is available navigate the user to the download URL
itms-services://?action=download-manifest&url=<url-path-to-plist>
and it will install over the existing version leaving all data in-tact and even upgrade the CoreData database if you setup auto migration and make changes.
Thanks to Joe for a fantastic response. Here is the extended version translated to swift. You can put it inside of the viewDidLoad
of your main view controller
let plistUrl = "https://example.com/example.plist"
let installationUrl = "itms-services://?action=download-manifest&url=https://example.com/example.plist"
override func viewDidLoad() {
super.viewDidLoad()
//Check for the updates
checkForUpdates()
}
func checkForUpdates() {
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
let updateDictionary = NSDictionary(contentsOfURL: NSURL(string: self.plistUrl)!)!
let items = updateDictionary["items"]
let itemDict = items?.lastObject as! NSDictionary
let metaData = itemDict["metadata"] as! NSDictionary
let serverVersion = metaData["bundle-version"] as! String
let localVersion = NSBundle.mainBundle().infoDictionary!["CFBundleVersion"] as! String
let updateAvailable = serverVersion.compare(localVersion, options: .NumericSearch) == .OrderedDescending;
if updateAvailable {
self.showUpdateDialog(serverVersion)
}
})
}
func showUpdateDialog(serverVersion: String) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let alertController = UIAlertController(title: "New version of Example available!", message:
"Example \(serverVersion) has been released. Would you like to download it now?", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Not now", style: .Cancel,handler: nil))
alertController.addAction(UIAlertAction(title: "Update", style: .Default, handler: { (UIAlertAction) in
UIApplication.sharedApplication().openURL(NSURL(string: self.installationUrl)!)
}))
self.presentViewController(alertController, animated: true, completion: nil)
})
}
Just distribute the update the same way you distribute the original. The user retains the data from the earlier version.