App版本更新(版本检测 & 引导更新)

注意: 苹果审核时是不允许app内有任何提示版本更新的内容, 否则拒绝上架

App由于增加新功能, 优化体验, 修复bug等情况需要不断更新版本, 为了给用户提供最好的体验, 往往希望新版本上架后所有的用户都可以最快的速度体验到最新的版本, 这就与苹果禁止App内提示版本更新的规定相冲突, 但是以下方法可以避过苹果的审核, 从而达到版本更新提示, 并引导到App Store更新.
原理: 在App启动的时候比较App Store中版本的版本号与本地App的版本号的大小, 如果App Store中的版本号大于本地App版本号, 提示版本更新, 否则不提示版本更新; 由于开发完一个新版本, 会修改一个版本号, 提交苹果审核的时候, 版本号一定是大于App Store中的版本号的, 所以苹果的审核人员在审核时是不会看到版本更新提示的, 而一旦上架成功, 由于App Store中最新的版本号大于用户已安装的版本的版本号, 自然就看得到版本更新提示, 用户可以直接点击立即更新, 然后直接跳转到App Store中此App的详情页面, 点击更新就ok了.
关于版本号: 关于版本号的设置, 感觉跟公司和程序员本身的习惯有很大关系, 如果领导管这个, 就是什么时候上什么版本, 领导都设计好了, 那你只需要听领导的就好了, 下面我只说一般情况: 都是在原来的基础上直接增加 1, 不过分具体情况, 一般如果只是普通的bug修复或者性能优化, 则是小版本号更新, 例如: 前一个版本是 1.3.1, 则新版本是 1.3.2; 而如果是增加新功能,UI有重大改变(重构), 修复重大bug等情况, 一般都是增加大版本, 例如: 前一个版本是 1.3.1, 则新版本可能是 1.4 或者 2.0 .

代码

注1: 可以单独将其抽离成一个工具类, 这样其他项目需要的时候, 只需要将这个类直接copy过去, 然后在需要的地方直接使用: AppVersionManager.shareManager.checkAppStoreVersion(), 就可以实现版本更新提示了, 其余什么都不需要做, 但是如果你对提示文本有自己的想法, 你就需要自己设置了)
注2: 下面代码中的"https://itunes.apple.com/cn/lookup?id=app对应的id"是获取app上架版本的信息的路径, "id="中=号后面则需要填写对应app的id, 那么如何知道这个id呢? 请看下图:
Apple ID.png
/// 检查APP版本信息
    func checkAppStoreVersion() {
        // 路径
        let checkUrlString = "https://itunes.apple.com/cn/lookup?id=app对应的id"
        let checkUrl = URL(string: checkUrlString)
        var request = URLRequest(url: checkUrl!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 15.0)
        request.httpMethod = "POST"
        URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, urlResponse, error) in
            if error == nil && data != nil {
                do {
                    let appInfo = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
                    if appInfo != nil {
                        let resultAry = appInfo!["results"] as! NSArray
                        let resultDic = resultAry.firstObject as! NSDictionary
                        // 版本号
                        self?.version = resultDic["version"] as? String
                        // 应用名称
                        let appName = resultDic["trackName"] as! String
                        // 下载地址
                        self?.trackViewUrlString = resultDic["trackViewUrl"] as? String
                        if self?.hasNew() == true {
                            self?.remindUpdateVersion()
                        }
                    }
                } catch let error as NSError {
                    print(error)
                }
            }
        })
    }
判断是否存在新版本
   fileprivate func hasNew() -> Bool {
        if version == nil {
            return false
        }
        // 获取当前版本号
        let infoDic = Bundle.main.infoDictionary
        let appVersion = infoDic!["CFBundleShortVersionString"] as! String
        /// NSComparisonResult: 升序:OrderedAscending, 降序:OrderedDescending, 相等:OrderedSame
        if appVersion.compare(version!, options: .numeric) == .orderedAscending {
            // 发现新版本
            return true
        } else {
            // 未发现新版本
            return false
        }
    }
如果存在新版本, 弹出提示
/// 提示有新版本
    fileprivate func remindUpdateVersion() {
        let alertController = UIAlertController.init(title: "版本更新", message: "新版本" + "(v\(version!))" + "已经上线了,等你来体验哦~", preferredStyle: UIAlertControllerStyle.alert)
        let alertActionDone = UIAlertAction.init(title: "立即更新", style: UIAlertActionStyle.default) { [weak self] (action) in
            let appStoreUrl = URL(string: self?.trackViewUrlString ?? "")
            if UIApplication.shared.canOpenURL(appStoreUrl!) {
                UIApplication.shared.openURL(appStoreUrl!)
            }
        }
        
        if alertActionDone.value(forKey: "titleTextColor") == nil {
            alertActionDone.setValue(UIColor.red, forKey: "titleTextColor")
        }
        
        let alertActionCancle = UIAlertAction.init(title: "以后再说", style: .cancel) { (action) in
            alertController.dismiss(animated: true, completion: nil)
        }
        
        alertController.addAction(alertActionDone)
        alertController.addAction(alertActionCancle)
        DispatchQueue.main.async {
              let appdelegate = UIApplication.shared.delegate as! AppDelegate
              appdelegate.window?.rootViewController?.present(alertController, animated: true, completion: nil)
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259