iOSアプリのアップデートをお知らせする

エンジニアの渡邉です。   前回のブログを投稿してから半年の間に 新しい営業が入り、メンバーも増えて…

エンジニアの渡邉です。
 

前回のブログを投稿してから半年の間に
新しい営業が入り、メンバーも増えて色々と刺激をもらってます。
 

現在開発中のアプリでアプリのアップデートをお知らせする機能が欲しいという話がありました。
よく見るこんなポップアップですね。
 

アップデートポップアップ
 

この機能を実装するにあたり、色々調べてみたのですが、
「サーバでアプリのバージョンデータを持っておいてアプリで取得して比較する」
という情報がほとんど。。。
 

サーバに持たせてもいいけど、
バージョンアップした度にサーバのデータを書き換えることになるので、
ヒューマンエラーの可能性を考えるとあまり良くないし、
サーバのどこにそのファイル置くの?
など色々考慮が必要で、どうしようかと考えてたら、
「Apple Storeから取ってこれないの?」と工藤先輩の一言。
 

確かに、Apple Storeからアプリのバージョンデータが取ってこれれば
サーバにファイルを置く必要もなければ、
ヒューマンエラーの可能性もない!
 

ということで、Apple Storeからアプリの情報を取ってくる方法を調べて、
バージョン情報が取ってこれることを確認。
 

https://itunes.apple.com/jp/lookup?id=\(APPLE_ID)

で取ってこれます。
 

試しに漫画カメラのデータを取ってみます。(長いので一部抜粋)

{
 "resultCount":1,
 "results": [{"isGameCenterEnabled":false,
 "trackCensoredName":"漫画カメラ",
 "minimumOsVersion":"7.0",
 "currency":"JPY",
 "wrapperType":"software",
 "version":"3.9.2",
 "formattedPrice":"無料",
 "userRatingCount":1316}]
}

 

この中の、”version”の情報がAppleStoreに出ている最新のバージョン情報になるので、
このデータを取ってきて、
インストールしているアプリのバージョンと比較すれば
インストールしているアプリが古いのかどうかが判断できます。
 

ということで実装してみます。

var util = UserUtil()
let APPLE_ID = "557883632" // AppIDを設定する。(現在は漫画カメラのAppIDです)

enum Version {
    case needUpdate
    case same
    case oldVersion
    case noAppStoreResult
}

class UserUtil: NSObject {
    override init() {
        super.init()
    }
    
    // アプリのバージョンチェック
    func checkVersion() -> Version {

        let url = "https://itunes.apple.com/jp/lookup?id=\(APPLE_ID)"
        let request = NSURLRequest(URL: NSURL(string: url)!,
                                                                      cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy,
                                                                      timeoutInterval: 60.0)
        let response:AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil

        do {
            // AppleStoreから情報を取得する
            let data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: response)
            let dataDic: AnyObject? = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions())

            // 取得したJSONファイルからversion情報を取得して端末のバージョンと比較
            let resultsArray = dataDic?.objectForKey("results") as! NSArray
            if resultsArray.count > 0 {
                let results = resultsArray[0] as! NSDictionary
                let storeVersion = results.objectForKey("version") as! NSString

                // 端末にインストールされているアプリのバージョンを取得
                let currentVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String

                // バージョンを比較
                if storeVersion.compare(currentVersion, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending {
                    // ストアのバージョンの方が新しい
                    print("store version is newer!")
                    return Version.needUpdate
                } else if storeVersion.compare(currentVersion, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame{
                    // ストアのバージョンと一致
                    print("store version is equal")
                    return Version.same
                } else {
                    // ストアのバージョンの方が古い
                    print("store version is older")
                    return Version.oldVersion
                }
            }
        } catch  {
            return Version.noAppStoreResult
        }
        return Version.noAppStoreResult
    }
    
    // アップルストアに飛ばす
    func openAppStore() {
        let urlString = "itms-apps://itunes.apple.com/app/id\(APPLE_ID)"
        let url = NSURL(string: urlString)
        UIApplication.sharedApplication().openURL(url!)
    }
}

 

上記内容でクラスを作成し、バージョン情報を比較したいViewControllerで以下の実装を行えば
インストールしているアプリが古い時にポップアップの表示が行えます。
今回のアプリでは、Splash画面表示時に呼ばれるViewControllerに記載しました。
 

if util.checkVersion() == Version.needUpdate {
    // ポップアップを出す
    let alertController = UIAlertController(title: "アプリアップデート", message: "最新のアプリをダウンロードしてください。", preferredStyle: .Alert)

    let okAction = UIAlertAction(title: "OK", style: .Default, handler: { (action: UIAlertAction) -> Void in
        util.openAppStore()
    })

    alertController.addAction(okAction)
    self.presentViewController(alertController, animated: false, completion: nil)
}

 

この方法だと自作のポップアップを表示するのもやりやすいし、
アプリのリリースのタイミングに合わせて修正する必要が無いので、ヒューマンエラーやタイムラグも防げますね。
 

開発を進ていくと色々とわからないことがたくさんありますが、
周りの人の知恵を借りつつ、色々助けられながら進めています。
会社の雰囲気もわからないことを聞きやすいのが良いですね!
毎日和気藹々としながら、引き締めるところは引き締めて日々開発を進めています!