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

68

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

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


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

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

代码的一部分是当版本不相等时确定你想要达到的目标,这是你将用户发送到应用商店下载最新版本的位置。


你能告诉我在我们的应用程序中我应该把那部分代码放在哪里吗?是必须要放在didFinishLaunchingWithOptions中还是其他地方?请指导我。 - Bhupat Bheda
@BhupatBheda,抱歉回复晚了。请从GIT克隆此代码,它将帮助您更好地理解。https://github.com/ArtSabintsev/Harpy当您将代码迁移到您的项目中时,您需要从harpybundle、harpy.h和harpy.m中获取所需内容。然后,您需要对您的appdelegate进行更改(将与其相同的内容复制并粘贴到您的app delegate中)。在“HarpyAlertType”中,您将有一个选项,您可以在项目中看到它,单击您想要在更新应用程序时向用户呈现的选项。然后您就可以忘记它。这将通过sub传递。 - C-H-E-F
@BhupatBheda,对于HarpyAlertType,您将有三个选项:HarpyAlertTypeSkip HarpyAlertTypeForce HarpyAlertTypeOption选择您希望显示的选项。希望我没有太晚回复并且能够帮到您,再次抱歉我在度假期间。 - C-H-E-F
嘿,谢谢您的回复,我会尝试按照您所提到的去做。谢谢! - Bhupat Bheda

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

0
可以使用以下代码检查应用程序版本号:
``` Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ```
然后将其与你的强制更新版本进行比较,如果需要则打开Appstore。
if let url = URL(string: "https://apps.apple.com/tr/app/--id--") {
    UIApplication.shared.open(url)
}

0

苹果不提供任何自动化的方式来完成这个任务,你需要手动编写。

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


0

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

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

GET: http://itunes.apple.com/lookup?id=


0
一个快速管理应用程序支持版本的方法是使用“kill switch”。您可以按照上面建议的方式自己实现它,或者您可以使用提供现成解决方案的服务,例如Semaphr

-17
当然没有办法。用户应该决定是否要下载你的应用程序的新版本。
AppStore将显示是否有新版本,所以我也不认为苹果公司会允许这样做。而且我也不知道你会怎么做?你可以通过互联网连接来检查它,但这并不是苹果公司喜欢的方式,所以你没有机会这样做。

4
我不同意,“强制用户更新”并不总是一个坏主意。比如,如果你开发了一款游戏,但用户发现了可以提高在线得分或成就的漏洞,那怎么办呢?开发者修复了这个漏洞并发布了更新,但如果不能强制用户更新,那么作弊者就不会“想要”升级,因为他们知道更新将防止他们作弊。如果你不能强制更新,那又该如何防止作弊者利用漏洞呢?无法做到!这对于喜欢你的游戏且选择不作弊的所有玩家来说都是一场灾难。你有什么想法? - BeachRunnerFred
思路没问题,但如果你强制更新,用户就失去了控制,这不好。这是用户的设备,他可以决定如何使用它。 - Tim
4
这句话的意思是:“这是用户的设备,他可以决定自己想用它做什么。”但实际上苹果并不允许你完全随心所欲地使用你的设备。 - memical
4
有时候,比如最近我使用的一款医疗应用程序,你肯定不想让孩子服用剂量错误的药物吧!:) - Ondrej Rafaj
你说没有办法?你总可以通过要求GPS数据访问来跟踪用户,然后去那里并指着他的头部用枪强迫他更新应用程序。当然,认真地说,你不能强迫用户做任何事情,但作为应用程序所有者,你肯定可以提供选项:更新或保留无用版本的应用程序 - 只是因为这是我的应用程序,我必须做出决策。而且你知道吗 - 我真的这样做是因为我为我的用户增加了更多价值,并且不想在一个更新只需要几秒钟的世界中浪费时间进行向后兼容性。 - tishma
答案不准确。 - JhonnyTawk

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