我可以强制 iPhone 用户升级应用程序吗?

68

当我的应用在iTunes商店中有新版本时,是否可以强制用户进行升级?

我目前正在开发一个应用程序。但是每次我上传一个新版本时,我希望能够强制用户进行升级,因为新版本拥有更多功能,而我想丢弃旧版本。 iPhone 默认是否支持此操作,还是我需要编写自己的实现来检查当前版本并将其与商店进行比较?


2
作为一名iPhone用户,我见过很多糟糕的更新。我更喜欢被给予选择是否更新。即使是苹果和微软也不会强制安全更新。你总是可以选择退出或恢复旧版本。如果是安全或功能要求,你可以告诉用户更新是必要的,否则应用程序将无法正常运行。你可以阻止他们的凭据直到他们更新,但这仍然是他们的选择。 如果你给我一个糟糕的更新,我会删除它并从iTunes恢复旧版本。 即使现在,用户也提出了iPhone请求,希望能够阻止应用程序更新。 - user790104
5
我自己也遇到了这个问题。我发布了一个名为Harpy的小工具,它会检查已安装版本和 App Store 版本是否一致。如果商店中有新版本可用,它会通知你的最终用户并在应用程序启动时提示他们下载该应用程序。在 Github 上获取它 - ArtSabintsev
我有一个应用程序处于同样的情况;它具有版本检查逻辑,因为我们希望能够在需要或想要时进行强制升级。早期的测试版由于具有此逻辑而被ITunes拒绝。我不明白的是,如果在IOS应用程序中使用Harpy,并且仅向用户提供“更新”选项,那么这是否允许,为什么?当我查看Harpy github信息时,我没有看到避免更新的方法,如果“更新”是唯一提供的选项(类似于我们所拒绝的内容)。重要的区别是保持iTunes作为主要信息来源还是外部信息来源吗? - Curtis Herrick
17个回答

39

我通过从iTunes网络服务获取版本并与当前版本进行比较来完成此功能...以下是我的代码

        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服务调用。


这真的很好。你还在使用上述概念吗?或者有任何限制吗?@Dilip Rajkuma - Ganesh G
嗨 @ganesh,我不是在开发iOS应用程序。但我猜它仍然可以工作,如果不能,请告诉我。 - Dilip Rajkumar
在我看来,WebService机制对于这种情况似乎有些过度。请参考@datinc的[NSData dataWithContentsOfURL:url]。但是请使用上面提到的lookup?id=<Your app ID>而不是datinc的`lookup?bundleid=..". - ToolmakerSteve
但是当应用程序处于“审核中”状态时,苹果如何进行审核呢?因为它每次只显示警报。我说得对吗? - user2526811
@DilipRajkumar,但当应用程序处于“审核中”状态时,苹果如何进行审核,因为它每次只显示警告。我对吗? - user2526811

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;
}

2
BundleIdentifier 可能会在每个新版本中更改。最好使用“应用程序 ID”,因为它不会改变。 - Ganesh G
1
为了澄清@GaneshGuturi的评论:将lookup?bundleId=替换为lookup?id=。 并使用您的应用程序的“Apple ID”,而不是查找捆绑标识符。 因此,在url =之前的两行无需;只需在您的应用程序的iTunes连接页面上硬编码“Apple ID”。 - ToolmakerSteve
这是一个好的答案,使用类似 [appStoreVersion compare:currentVersion options:NSNumericSearch] == NSOrderedDescending 的方法来比较两个版本可能也是可取的,例如如果您想避免潜在的App Store审核问题,因为正在审核的版本将始终与App Store版本不同。当然,这仅适用于每次发布都增加版本号(而不是从版本2.0.0到1.0.0)。 - DARKMATTER

18
这个问题最初发布于7年前,尽管某些答案仍然相关,但现在有了更新的方法。
我推荐使用Swift 3兼容的https://github.com/ArtSabintsev/Siren库,可以通过Cocoapods或Carthage安装。
CocoaPods,支持Swift 3: pod 'Siren' Carthage: github "ArtSabintsev/Siren"

它可以运行于 Swift 5 - Mamad Farrahi

17

如果你非常必要,可以启动应用商店,让你的用户可以从中获取最新版本。我建议将此作为可选项,或者至少先呈现对话框。

// 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]];

但是如何确定商店里的东西是否是更新版本? - ToolmakerSteve
@ToolmakerSteve - 你可以从iTunes页面上爬取最新版本,或者更简单的方法是保留一个包含最新版本信息的小型HTML文件,并从客户端检查它。当然还有其他方法。 - BadPirate

9

没有自动化的方法可以完成这个任务,您需要手动编写代码。


请看这个:https://github.com/ArtSabintsev/Siren - Mamad Farrahi

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

*编辑* 这个答案已经不正确了。请查看其他赞同的答案以获取当前的真相。


谢谢解释。我必须尝试一下,因为对于我的应用程序来说,明确的升级是必需的。目前版本处理免费订阅,升级必须包括付款。这就是我试图强制保持它的原因。 - Nareshkumar
2
@HariKaramSingh,是的,您可以使用其他问题中提到的方法。不幸的是,在它被标记为已接受答案之前,我无法删除此答案。 - Vladimir
@Vladimir,您可能无法删除,但您始终可以更新。这将作为一个更新的参考,供以后遇到此问题的人使用。 - Mudassir

8
每个应用程序都应该包含一个强制升级系统,如果应用程序对外部内容有依赖关系。苹果和谷歌都声称,如果应用程序使用了外部API,则该外部API应该永远存在,永不更改等等,但这是不现实的。如果这是事实,那么如果应用程序依赖的服务可以更改,那么必须有一种方法让应用程序检查并查看是否应该限制功能,并提示用户获取最新版本,否则事情将会神秘地失败。
这可能也应该是苹果和谷歌提供的东西,但他们没有这样做,因此除了少数游戏之外的每个应用程序都需要构建这个东西,所以...
我开始了一个基于rails的开源(Apache 2.0)项目来解决这个问题。它被称为Application-[Ctrl],它仍然在不断发展中,但您可以使用它,我欢迎任何形式的贡献。如果我能在空闲时间内将其运行起来,我将向所有应用程序开发人员提供某些非常合理的免费服务,并且当然每家公司都将能够启动自己的部署。

这里是 GitHub 上的链接:https://github.com/SlalomDigital/ApplicationCtrl

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


6

我的应用更新在应用商店被拒绝,原因就是这个。我们添加了一个功能来检查已安装版本和当前版本的差异,如果不支持该版本,我们会强制用户更新。

苹果公司拒绝了这个功能。

所以只能回到设计阶段重新规划!


我很好奇,他们指明了这违反了哪个应用商店的指南? - mpoisot
我有一个应用程序也处于同样的情况;它具有版本检查逻辑,因为我们希望能够在需要或想要时进行强制升级。早期的测试版因为有这个逻辑而被拒绝了。你的应用程序的版本检查逻辑为什么不被允许,但是从各种帖子中看来,Harpy是被允许的呢? - Curtis Herrick
6
他们是如何发现你会显示这个屏幕的呢?因为他们总是用最新版进行测试。 - José
2
我们的iOS应用程序还具有强制更新功能,它会检查Web服务的最低支持版本,并在需要时进行强制更新。它从未被拒绝过。 - crypt

4
你的业务/设计计划中不应该包含“强制用户”这个词语。当你强迫用户做某些事情时,他们会感到愤怒。想象一下一个匆忙打开你的小应用程序的用户,却发现你强制他升级才能使用所需功能。想象一下他被困在荒野之中,只能使用Edge进行下载。他不会高兴的。
如果你按照这个计划长期操作,你的升级中必然会出现显著的错误。如果你强迫用户使用有错误的版本,他们会反叛。
我的经验告诉我,每当我看到“更多功能”用于描述软件新版本时,我就会感到不安,因为这通常意味着功能膨胀。设计师往往会不断地将更多功能添加到应用程序中,直到一个应用程序可以完成所有任务。这在像iPhone这样的平台上特别危险,因为让一个应用程序做太多的事情会迅速压垮界面和应用程序的响应速度。
编辑01:我的评论“如何在用户付费升级后更新应用程序”也可能与您的计划相关。如果您的升级设计使苹果失去收入,那么这是不可行的。
更新:
只是为了澄清下面的评论:是的,有时你确实需要要求用户升级。然而,这与从一开始就设计应用程序强制用户每次开发人员发布新版本都必须升级是完全不同的。
这样的设计旨在让开发人员的生活变得容易,而不是用户的生活。每当用户不得不花费时间进行升级以获得他们没有要求且可能不想要的好处时,你就会从客户那里拿走时间和资源。将时间和精力从开发人员转移到用户的设计是不好的设计,因为人们最终购买软件是为了自己的利益。当你减少了这种利益时,你就降低了软件的最终盈利能力。
因此,除非是绝对必要的技术需求,否则没有设计师应该设计强制用户做不愿意做的事情的软件。这当然是一个经验法则,但它是一个非常好的经验法则。

8
我同意“强制使用者”的行为确实很糟糕。但是,在某些情况下,强制更新路径可能是相关的。例如,我正在开发一个基于多用户持久化服务器的游戏(有点像MMORPG),每当我添加可能与旧版本不兼容的功能时,我需要强制更新。不过这是一个奇怪的用例。大多数情况下,可以设计出更好的解决方案。 - BadPirate
8
强制用户更新并不总是一个坏主意。比如说,如果你开发了一款游戏,用户发现了一个漏洞可以欺骗在线得分或成就,那该怎么办呢?如果开发者修复了这个漏洞并发布了更新,作弊者将不会愿意升级,因为他们知道这个更新将防止他们继续作弊。如果不能强制更新,那么你如何防止作弊者继续使用漏洞呢?你无法做到!这对于所有喜欢你的游戏并选择不作弊的玩家来说都是一场灾难。你有什么想法吗? - BeachRunnerFred
4
我不同意,当然有时需要强制用户更新。 - Anders Lindén
20
我不明白为什么这篇帖子会被投票赞同这么多。原帖并没有问“我应该强制 iPhone 用户升级应用程序吗?”所以这个回复并没有回答问题,只是一篇意见文章。有很多合理的理由需要强制用户升级。只需看看 Xbox Live,它已经在生产中运行了多年,并且拥有非常庞大的用户群体。每次有新更新可用时,它都需要用户更新仪表板。 - OpenUserX03
11
我已经给这个答案点了踩。我不傻,我不需要一篇说教的回答。我知道如果没有充分理由的话强迫用户做某事并不是一个好主意。我碰巧有一个非常好的理由去这么做,我来这里是希望找到最好的方式来完成它。 - Chris Harrison
显示剩余9条评论

4
其他答案表明,人们必须自己实现强制更新功能。 真是一件遗憾的事情,我希望不是这样的。 我的iOS应用程序第一个更新将于明天发布,幸运的是,这不会成为问题,因为我们只对应用程序进行了更改。 然而,当我们最终更改我们的Web服务结构时,强制更新将非常有用,这样我们的服务器就不必支持每个应用程序版本。
然而,还有另一种替代方法,似乎在这个线程中没有提到。 您可以让每个生成数据的Web服务调用附加一个模式到该数据上, 它告诉应用程序如何反序列化该数据。 这使您可以更改由get请求生成的数据结构,而不会破坏应用程序中的反序列化。 当然,这假设您编写的解释器本身不会更改,但当它成熟时,这是一个相当合理的假设。
通过交互,可以“模式化”Post请求。 我的意思是,在您进行每个Post请求之前,您都会要求关于如何调用最新的Web服务的指示。 您使用附加的计划来处理说明,然后进行实际的调用到Web服务。 基本上,这意味着每个Post请求需要2个请求,但这可能没关系。
然而,无论您实现强制更新还是模式解释,该功能都必须从应用程序进入App Store的第1天开始存在。 否则你会陷入同样的困境。如果苹果公司为我们开发人员实现了强制更新,所有这些复杂性都是不必要的。 如果强制更新存在,模式解释仍将是一种可用性改进。 但让我有点困扰的是,苹果没有强制更新,因为至少有了它,我们可以在应用程序发布后引入自己的防护性更新措施。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接