62

一旦 iTunes Store 中有我的应用程序的新版本可用,是否可以强制用户升级?

我目前正在开发一个应用程序。但是,我想在上传新版本时强制升级,因为升级会有更多功能,我想丢弃以前的版本。默认情况下这可能与 iPhone 或我必须编写自己的实现来检查当前版本并将其与商店进行比较?

4

16 回答 16

38

我通过从 itunes webservice 获取版本并与当前版本进行比较来完成此功能。以下是我的代码

        NSString *version = @"";
        NSURL *url = [NSURL URLWithString:@"http://itunes.apple.com/lookup?id=<Your app ID>"];
        versionRequest = [ASIFormDataRequest requestWithURL:url];
        [versionRequest setRequestMethod:@"GET"];
        [versionRequest setDelegate:self];
        [versionRequest setTimeOutSeconds:150];
        [versionRequest addRequestHeader:@"Content-Type" value:@"application/json"]; 
        [versionRequest startSynchronous];

        //Response string of our REST call
        NSString* jsonResponseString = [versionRequest responseString];

        NSDictionary *loginAuthenticationResponse = [jsonResponseString objectFromJSONString];

        NSArray *configData = [loginAuthenticationResponse valueForKey:@"results"];

        for (id config in configData) 
        {
            version = [config valueForKey:@"version"];
        }
   //Check your version with the version in app store
        if (![version isEqualToString:[itsUserDefaults objectForKey:@"version"]]) 
        {
            ProAlertView *createUserResponseAlert = [[ProAlertView alloc] initWithTitle:@"New Version!!" message: @"A new version of app is available to download" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles: @"Download", nil];
        [createUserResponseAlert show]; 
        [createUserResponseAlert release];
        }

并将应用程序ID放在iTunes链接中,请参见下面的代码..

- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    // the user clicked one of the OK/Cancel buttons
    if (buttonIndex == 1)
    {
        NSString *iTunesLink = @"itms-apps://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftwareUpdate?id=<appid>&mt=8";
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:iTunesLink]];
    }
}

注意:您需要 JSONKit 框架和 ASIHttp 框架来进行 web 服务调用。

于 2012-01-24T14:11:54.570 回答
22

您可以检测应用程序是否需要更新,然后采取一些自定义操作,例如提醒用户有可用更新。这是一个检测更新可用的代码片段。

-(BOOL) needsUpdate{
    NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString* appID = infoDictionary[@"CFBundleIdentifier"];
    NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
    NSData* data = [NSData dataWithContentsOfURL:url];
    NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

    if ([lookup[@"resultCount"] integerValue] == 1){
        NSString* appStoreVersion = lookup[@"results"][0][@"version"];
        NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];
        if (![appStoreVersion isEqualToString:currentVersion]){
            NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
            return YES;
        }
    }
    return NO;
}
于 2014-08-08T18:34:56.750 回答
17

如果您绝对需要,您可以启动 App Store,以便您的用户可以从那里获得最新版本。我建议将此设置为可选,或者至少先进行对话。

// iTunesLink should be your applications link
NSString *iTunesLink = @"http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=284417350&mt=8";


[[UIApplication sharedApplication] openURL:[NSURL URLWithString:iTunesLink]];
于 2010-08-31T20:14:36.953 回答
15

这个问题最初是在 7 年前发布的,虽然其中一些答案仍然相关,但这里有一个更新的方法。

我推荐https://github.com/ArtSabintsev/Siren,它与 Swift 3 兼容,可以与 Cocoapods 或 Carthage 一起安装。

CocoaPods、Swift 3 支持:

pod 'Siren'

迦太基:

github "ArtSabintsev/Siren"

于 2017-04-12T11:21:57.437 回答
8

没有自动化的方法可以做到这一点,你必须手动编写一些东西。

于 2010-02-08T12:18:18.183 回答
8

系统处理应用程序更新的唯一方法是提示用户标准 AppStore 应用程序中有可用的更新。
此外,独立应用程序不知道可用更新,因此您需要实现 Web 服务,应用程序可以检查当前版本是否有效。
而且我不确定这是否符合Apple关于应用程序的规则,例如(虽然找不到证明链接)您不能上传应用程序的试用版。

* 编辑 * 这个答案不再正确。有关当前真相,请参阅其他赞成的答案。

于 2010-02-08T12:20:58.207 回答
8

强制升级系统应该是每个应用程序的一部分,该应用程序依赖于该应用程序的外部事物。苹果和谷歌都声称,如果一个应用程序使用外部的东西,那么这个外部 API 应该永远存在,永远不会改变,等等,但这是不现实的。如果是这种情况,如果应用程序依赖的服务可以更改,那么应用程序必须有一种方法来检查它是否应该限制功能并提示用户获取最新版本,否则事情就会神秘地失败。

这可能而且应该是 Apple 和 Google 提供的东西,但他们不是这样的,所以除了一些游戏之外的每个应用程序都需要构建它,所以......

我已经启动了一个基于 Rails 的开源 (Apache 2.0) 项目来为这个问题创建一个解决方案。它被称为 Application-[Ctrl],这是一项正在进行中的工作,但欢迎您使用它,我欢迎任何形式的贡献。如果我能在业余时间启动并运行它,我将为所有应用程序开发人员提供一些非常合理的免费服务,当然每家公司都将始终能够启动它自己的部署。

它在 GitHub 上:https ://github.com/SlalomDigital/ApplicationCtrl

贡献并帮助我解决这个问题!

于 2013-04-22T22:59:22.110 回答
5

正是由于这个原因,我对 App Store 的应用更新被拒绝了。我们添加了一项功能,可以根据当前版本检查已安装的版本,如果它不是受支持的版本,我们会强制它们进行更新。

苹果拒绝了这一点。

所以回到设计板!

于 2017-03-01T11:53:41.657 回答
4

你的商业/设计计划不应该包含“强迫用户”的短语。当你让他们做某事时,他们会生气。想象一下,一个用户匆匆忙忙地打开了你漂亮的小应用程序,却发现你在强迫他升级,然后他才能使用应用程序来满足他的需要。想象一下,他不得不使用 Edge 下载。他不会高兴的。

如果您遵循此计划足够长的时间,您的其中一个升级将不可避免地引入一个明显的错误。如果你强迫用户使用有缺陷的版本,他们会反抗。

每当我看到用于描述新版本软件的“更多功能”时,我都会因经验而畏缩,因为这不可避免地意味着功能膨胀。设计师倾向于不断将越来越多的功能移植到应用程序上,直到一个应用程序完成所有工作。这在像 iPhone 这样的平台上尤其危险,因为让一个应用程序做很多事情会迅速压倒应用程序的界面和响应能力。

Edit01:我在这里的评论如何在用户付费升级后更新应用程序也可能与您的计划有关。如果您的升级设计将 Apple 排除在收入循环之外,那么它就不是首发了。

更新:

只是根据下面的评论澄清一下:是的,有时您确实必须要求用户升级。然而,这与从一开始就设计应用程序以强制用户在每次开发人员发布新版本时进行升级有很大不同。

这样的设计旨在使开发人员的生活更轻松,而不是用户的。每次用户不得不花时间升级以获得他们没有要求并且可能不想要的好处时,您已经从客户那里花费了时间和资源。将开发人员的时间和精力转移给用户的设计是糟糕的设计,因为人们最终会为自己的利益购买软件。当您降低该收益时,您会降低软件的最终盈利能力。

因此,任何设计师都不应该设计强迫用户做用户不希望做的事情的软件,除非这是绝对的技术需要。这当然是一个经验法则,但它是一个非常好的法则。

于 2010-02-08T13:14:51.530 回答
4

其他答案表明必须自己实现强制更新功能。真的很可惜,我希望不是这样。我对 iOS 应用程序的第一次更新将于明天发布,幸运的是这不会有问题,因为我们只是对应用程序进行了更改。然而,当我们最终改变我们的网络服务的结构时,能够强制更新将非常有用,这样我们的服务器就不必支持每个应用程序版本。

然而,有一种强制更新的替代方法,在这个线程中似乎没有提到。您可以让每个生成数据的 Web 服务调用都将一个模式附加到数据中,该模式告诉应用程序应该如何在您的应用程序中反序列化该数据。这使您能够更改 get-requests 生成的数据结构,而不会破坏应用程序中的反序列化。当然,这是假设您编写的解释器本身不会改变,但当它成熟时,这是一个有点合理的假设。

发布请求可以通过交互“模式化”。我的意思是,在您提出每个后请求之前,您会询问有关如何调用最新 Web 服务的说明。为此,您使用附加的模式处理指令,然后对 Web 服务进行实际调用。本质上,这意味着每个 post 请求都需要 2 个请求,但这没关系。

但是,无论您是实施强制更新还是模式解释,该功能都必须从应用商店的第一天开始就存在于应用程序中。否则你会陷入同样的​​困境。如果 Apple 为我们的开发人员实施强制更新,那么所有这些复杂性都是不必要的。如果存在强制更新,模式解释仍然是可用性改进。但是让我有点不爽的是,苹果没有强制更新,因为至少有了它,可以在应用发布后引入自己的防破解更新措施。

于 2015-08-01T16:04:57.260 回答
3

以后的任何人你好,我发现这个教程应该可以帮助任何人,它帮助了我。

http://codewithchris.com/tutorial-how-to-implement-in-app-update-functionality-in-your-iphoneipad-app/

编辑(您的代码将类似于以下内容):

// Try to get version 
NSString *versionNumber = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];

NSURL *updateUrl = [NSURL URLWithString:@"http://yourdomain.com/yourupdatefile.xml"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:updateUrl
                                            cachePolicy:NSURLCacheStorageNotAllowed
                                        timeoutInterval:20.0];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest
                                     returningResponse:&response
                                                 error:&error];
// Check no error, then parse data
if (error == nil)
{
    // Parse response into a dictionary
    NSPropertyListFormat format;
    NSString *errorStr = nil;
    NSDictionary *dictionary = [NSPropertyListSerialization propertyListFromData:data
                                                                mutabilityOption:NSPropertyListImmutable
                                                                          format:&format
                                                                errorDescription:&errorStr];        
    if (errorStr == nil)
    {
        @try {

            // Try to see if the current app version exists in the update xml
            NSString *itunesUrl = [dictionary objectForKey:versionNumber];

            if (itunesUrl)
            {
                // Show dialog to ask user to update!
            }
            else {
                // Version not in XML
            }
        } @catch (NSException *e) {
            // Error with retrieving the key
        }
    }
    else {
        // Error with parsing data into dictionary
    }
}

但是,经过进一步研究,我发现如果您不使用服务器,这是一个很好的解决方案。

-(BOOL) needsUpdate{
    NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString* appID = infoDictionary[@"CFBundleIdentifier"];
    NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
    NSData* data = [NSData dataWithContentsOfURL:url];
    NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

    if ([lookup[@"resultCount"] integerValue] == 1){
        NSString* appStoreVersion = lookup[@"results"][0][@"version"];
        NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];
        if (![appStoreVersion isEqualToString:currentVersion]){
            NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
            return YES;
        }
    }
    return NO;
}

在里面:

if (![appStoreVersion isEqualToString:currentVersion]){
                NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
                return YES;
            }

如果不相等,您设置的代码部分是您要执行的操作,这是您将用户发送到应用商店以下载最新版本的地方。

于 2016-07-21T21:22:10.810 回答
1
func appUpdateAvailable() -> (Bool,String?) {
        
        guard let info = Bundle.main.infoDictionary,
              let identifier = info["CFBundleIdentifier"] as? String else {
            return (false,nil)
        }
        
//        let storeInfoURL: String = "http://itunes.apple.com/lookup?bundleId=\(identifier)&country=IN"
        let storeInfoURL:String = "https://itunes.apple.com/in/lookup?bundleId=\(identifier)"
        var upgradeAvailable = false
        var versionAvailable = ""
        // Get the main bundle of the app so that we can determine the app's version number
        let bundle = Bundle.main
        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(contentsOf: urlOnAppStore! as URL) {
                // Try to deserialize the JSON that we got
                if let dict: NSDictionary = try? JSONSerialization.jsonObject(with: dataInJSON as Data, options: JSONSerialization.ReadingOptions.allowFragments) as! [String: AnyObject] as NSDictionary? {
                    if let results:NSArray = dict["results"] as? NSArray {
                        if let version = (results[0] as! [String:Any])["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
                                    versionAvailable = version
                                }
                            }
                        }
                    }
                }
            }
        }
        return (upgradeAvailable,versionAvailable)
    }
于 2021-08-16T11:20:17.810 回答
0

您可以使用以下网址获取任何应用程序的信息您只知道您的应用程序的 Apple ID。

itunesconnect.com您可以在>您的应用>应用信息页面中获取此 Apple ID

获取: http: //itunes.apple.com/lookup ?id=

于 2017-06-08T06:41:10.250 回答
0

您可以检查应用程序内部版本号

Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? 细绳

然后与您的强制更新版本进行比较,如果您想打开 Appstore。

if let url = URL(string: "https://apps.apple.com/tr/app/--id--") {
    UIApplication.shared.open(url)
}
于 2021-05-28T21:51:40.837 回答
0

Apple 没有提供任何自动化的方式来做到这一点,您必须手动编写。

选项 1. 可以使用 iTunes API 检查该特定 App id 的最新版本。并显示弹出窗口以更新应用程序。选项2:您可以使用自己的服务器检查最新版本。但是每当有任何更新进入苹果应用商店时,您都必须更新您的服务器。

于 2021-09-24T13:38:36.067 回答
-16

当然没有办法。用户应该决定是否要下载您的应用程序的较新版本。

如果有新版本,AppStore 会显示,所以我也不认为 Apple 会允许这样做。另外我不知道你会怎么做?您可以通过互联网连接进行检查,但这不是 Apple 喜欢的方式,因此您没有机会这样做。

于 2010-02-08T12:37:19.220 回答