├── Classes ├── HSLUpdateChecker.h └── HSLUpdateChecker.m ├── HSLUpdateChecker.podspec ├── LICENSE └── README.md /Classes/HSLUpdateChecker.h: -------------------------------------------------------------------------------- 1 | // 2 | // HSLUpdateChecker.h 3 | // HSL Common Library 4 | // 5 | // Created by John Arnold on 2012-08-14. 6 | // Copyright (c) 2012-2013 Handelabra Studio LLC. All rights reserved. 7 | // 8 | 9 | /** 10 | Simple update checker, requires iOS 5+ and ARC. 11 | 12 | It uses your app's bundle identifier to ask the app store about the app, 13 | and if the version on the app store is different, it presents an alert with 14 | the "What's New" text and a button to go directly to the app store. 15 | 16 | The check and alert will only be performed once per new app store version 17 | (so that if a user declines, they do not continue to get bothered). 18 | */ 19 | @interface HSLUpdateChecker : NSObject 20 | 21 | /** Checks for update and presents a UIAlertView if there is an update available. 22 | 23 | */ 24 | + (void) checkForUpdate; 25 | 26 | /** Checks for update and calls the handler block to present your own UI or do whatever you want. 27 | 28 | @param handler Block that is only called if an update is available. 29 | */ 30 | + (void) checkForUpdateWithHandler:(void (^)(NSString *appStoreVersion, NSString *localVersion, NSString *releaseNotes, NSString *updateURL))handler; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Classes/HSLUpdateChecker.m: -------------------------------------------------------------------------------- 1 | // 2 | // HSLUpdateChecker.m 3 | // HSL Common Library 4 | // 5 | // Created by John Arnold on 2012-08-14. 6 | // Copyright (c) 2012-2013 Handelabra Studio LLC. All rights reserved. 7 | // 8 | 9 | #import "HSLUpdateChecker.h" 10 | 11 | @interface HSLUpdateChecker () 12 | 13 | @property (nonatomic, copy) NSString *updateUrl; // We need to remember the URL for the default alert handler 14 | 15 | @end 16 | 17 | @implementation HSLUpdateChecker 18 | 19 | + (HSLUpdateChecker *) sharedUpdateChecker 20 | { 21 | static dispatch_once_t pred = 0; 22 | __strong static id _sharedObject = nil; 23 | 24 | dispatch_once(&pred, ^{ 25 | _sharedObject = [[self alloc] init]; 26 | }); 27 | return _sharedObject; 28 | } 29 | 30 | + (void)checkForUpdate 31 | { 32 | [self checkForUpdateWithHandler:^(NSString *appStoreVersion, NSString *localVersion, NSString *releaseNotes, NSString *updateURL) { 33 | 34 | // Remember the URL for the alert delegate 35 | [HSLUpdateChecker sharedUpdateChecker].updateUrl = updateURL; 36 | 37 | NSString *titleFormat = NSLocalizedString(@"Version %@ Now Available", @"HSLUpdateChecker upgrade alert message title. The argument is the version number of the update."); 38 | NSString *messageFormat = NSLocalizedString(@"New in this version:\n%@", @"HSLUpdateChecker upgrade alert message text. The argument is the release notes for the update."); 39 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:titleFormat, appStoreVersion] 40 | message:[NSString stringWithFormat:messageFormat, releaseNotes] 41 | delegate:[HSLUpdateChecker sharedUpdateChecker] 42 | cancelButtonTitle:NSLocalizedString(@"Not Now", @"HSLUpdateChecker upgrade alert 'Not Now' button.") 43 | otherButtonTitles:NSLocalizedString(@"Update", @"HSLUpdateChecker upgrade alert 'Update' button."), nil]; 44 | [alert show]; 45 | }]; 46 | } 47 | 48 | + (void) checkForUpdateWithHandler:(void (^)(NSString *appStoreVersion, NSString *localVersion, NSString *releaseNotes, NSString *updateURL))handler 49 | { 50 | // Go to a background thread for the update check. 51 | dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 52 | dispatch_async(queue, ^{ 53 | NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier]; 54 | NSLocale *locale = [NSLocale currentLocale]; 55 | NSString *countryCode = [locale objectForKey:NSLocaleCountryCode]; 56 | NSString *languageCode = [locale objectForKey:NSLocaleLanguageCode]; 57 | NSString *urlString = [NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@&country=%@&lang=%@", bundleId, countryCode, languageCode]; 58 | NSURL *url = [NSURL URLWithString:urlString]; 59 | 60 | NSError *error = nil; 61 | NSData *jsonData = [NSData dataWithContentsOfURL:url]; 62 | 63 | if (jsonData) 64 | { 65 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error]; 66 | 67 | if (error) 68 | { 69 | NSLog(@"HSLUpdateChecker: Error parsing JSON from iTunes API: %@", error); 70 | } 71 | else 72 | { 73 | NSArray *results = dict[@"results"]; 74 | if (results.count > 0) 75 | { 76 | NSDictionary *result = results[0]; 77 | NSString *appStoreVersion = result[@"version"]; 78 | 79 | // We first try for CFBundleShortVersionString which is normally the user-visible version string 80 | NSString *localVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 81 | if (!localVersion) 82 | { 83 | // Try using CFBundleVersion instead 84 | localVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; 85 | } 86 | 87 | if (localVersion && ![localVersion isEqualToString:appStoreVersion]) 88 | { 89 | // Different! Tell our handler about it if we haven't already for this appStoreVersion. 90 | NSString *checkedAppStoreVersionKey = [NSString stringWithFormat:@"HSL_UPDATE_CHECKER_CHECKED_%@", appStoreVersion]; 91 | if (![[NSUserDefaults standardUserDefaults] boolForKey:checkedAppStoreVersionKey]) 92 | { 93 | [[NSUserDefaults standardUserDefaults] setBool:YES forKey:checkedAppStoreVersionKey]; 94 | [[NSUserDefaults standardUserDefaults] synchronize]; 95 | 96 | NSString *updateUrl = result[@"trackViewUrl"]; 97 | NSString *releaseNotes = result[@"releaseNotes"]; 98 | 99 | // If either of these are nil, don't do anything. 100 | if (updateUrl && releaseNotes) { 101 | dispatch_async(dispatch_get_main_queue(), ^{ 102 | if (handler) 103 | { 104 | handler(appStoreVersion, localVersion, releaseNotes, updateUrl); 105 | } 106 | }); 107 | } 108 | } 109 | } 110 | } 111 | } 112 | } 113 | else 114 | { 115 | // Handle Error 116 | NSLog(@"HSLUpdateChecker: Received no data from iTunes API"); 117 | } 118 | }); 119 | } 120 | 121 | #pragma mark - UIAlertViewDelegate methods 122 | 123 | - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex 124 | { 125 | if (buttonIndex == alertView.firstOtherButtonIndex) 126 | { 127 | // Go to the app store 128 | NSURL *url = [NSURL URLWithString:self.updateUrl]; 129 | [[UIApplication sharedApplication] openURL:url]; 130 | } 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /HSLUpdateChecker.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "HSLUpdateChecker" 3 | s.version = "1.0.2" 4 | s.summary = "Prompts the user to update your app when a new version is available. Deprecated because of reports of rejection, use at your own risk!" 5 | s.homepage = "https://github.com/Handelabra/HSLUpdateChecker" 6 | s.license = "MIT" 7 | s.author = { "John Arnold" => "john@handelabra.com" } 8 | s.source = { :git => "https://github.com/Handelabra/HSLUpdateChecker.git", :tag => "1.0.2" } 9 | s.platform = :ios, '5.0' 10 | s.source_files = 'Classes', 'Classes/**/*.{h,m}' 11 | s.requires_arc = true 12 | s.deprecated = true 13 | end 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 Handelabra Studio LLC. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HSLUpdateChecker 2 | ================ 3 | 4 | **IMPORTANT NOTE:** This code is deprecated due to reports of rejection by Apple. Example: https://github.com/Handelabra/HSLUpdateChecker/issues/7 5 | 6 | Simple update checker for iOS apps that displays an alert view with update release notes and the option to go to the App Store when an update for your app is available on the App Store. 7 | 8 | Simply drop it into your app project and call the class method checkForUpdate at an appropriate time after app launch completes. It stores its data in user defaults and only prompts users to update once per version. 9 | 10 | It uses the iTunes search API to lookup your app info by its bundle identifier. 11 | http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html 12 | 13 | Requires iOS 5+, ARC, and Apple Generic Versioning (see below). 14 | http://useyourloaf.com/blog/2010/08/18/setting-iphone-application-build-versions.html 15 | --------------------------------------------------------------------------------