iOS アプリのプロビジョニングプロファイルの有効期限をアプリ内で取得・表示する Swift コード
無料の Apple Developers Program アカウントを使っている場合、iOS にインストールした開発用アプリの有効期限は7日間で切れてしまう。
この有効期限までの残日数を、アプリ内で取得・表示させられないか調べてみた。
検証環境
- macOS Mojave
- Xcode v10.1
- Swift v4.2.1
- 参考 : 【Swift】Swiftのversionを確認しよう - Qiita …
$ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift --version
で確認
- 参考 : 【Swift】Swiftのversionを確認しよう - Qiita …
- iOS v12.0.1
アプリ内でプロビジョニングプロファイルの有効期限を知る方法
早速だが、以下のようなコードで、プロビジョニングプロファイルの有効期限を取得できる。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// ココでは画面上に置いたボタンをタップした時に実行するよう設定した
@IBAction func onTapBtn(_ sender: Any) {
// embedded.mobileprovision ファイルを取得する
guard let url = Bundle.main.url(forResource: "embedded", withExtension: "mobileprovision") else {
print("ファイル取得失敗")
return
}
// plist としてパースする際にゴミになる箇所をちぎるための処理
guard let data = try? Data(contentsOf: url),
let start = "<?xml".data(using: .utf8),
let end = "</plist>".data(using: .utf8),
let startRange = data.range(of: start),
let endRange = data.range(of: end) else {
print("ファイル準備失敗")
return
}
// 余計な場所をちぎり plist から「ExpirationDate」キーの値を抜き出す
let range = Range(uncheckedBounds: (lower: startRange.lowerBound, upper: endRange.upperBound))
let body = data.subdata(in: range)
guard let dictionary = try? PropertyListSerialization.propertyList(from: body, options: [], format: nil),
let plist = dictionary as? [String: Any],
let expireDate = plist["ExpirationDate"] as? Date else {
print("plist 変換失敗")
return
}
// ExpirationDate の値を日付形式に整形する
let dateFormat = DateFormatter()
dateFormat.locale = Locale.current
dateFormat.timeZone = TimeZone.current
dateFormat.dateFormat = "yyyy-MM-dd"
print("期限日 (YYYY-MM-DD)", dateFormat.string(from: expireDate)) // 「2019-01-07」などが取れる
// 現在日と比較して有効期限切れまでの残日数を計算する
let calendar = NSCalendar.current
let fromDate = calendar.startOfDay(for: Date())
let toDate = calendar.startOfDay(for: expireDate)
let components = calendar.dateComponents([.day], from: fromDate, to: toDate)
print("残日数", components.day!) // 「7」などが取れる
}
}
このコードの大部分の元ネタは以下より。
Objective-C な以下のコードも参考になるかも。
- 参考 : Detect if you're currently running a development version or an App Store/Ad Hoc version. · GitHub
やっていることは、
- アプリに同梱されているプロビジョニングプロファイル
embedded.mobileprovision
を取得する - その中から plist (XML) 部分を抜き出す
- その中から
ExpirationDate
プロパティの値 (Date
≒NSDate
) を取得する
というのが主なモノ。
あとは表示用に整形したり、現在日との比較で有効期限切れまでの残日数を計算したりしている。
- 参考 : ios - Swift days between two NSDates - Stack Overflow … 2つの日付間の日数を調べる方法
iOS シミュレータで動かした場合はプロビジョニングプロファイルが要らないので、print("ファイル取得失敗")
部分の return
で抜けてしまう。
2つの日付を比較して日数を調べる方法
残日数の比較は、もう少し簡素なやり方もある。結果が小数になることに留意。
let span = expireDate.timeIntervalSinceNow
let daySpan = span / 60 / 60 / 24
print("残日数", daySpan) // 6.99... などになる
他にも、人間が読みやすい形式に変換してくれるモノもあった。
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.allowedUnits = [.day]
dateComponentsFormatter.maximumUnitCount = 1
print("残日数", dateComponentsFormatter.string(from: Date(), to: expireDate)!) // "6d" などになる
- 参考 : 【iOS】X日やX時間などの文字列表現を簡単に作れる DateComponentsFormatter
- 参考 : ios 2つのNSDateの差を(月/日/時/分/秒)で取得する swift macos - CODE Q&A 問題解決
有効期限の期間自体を知る方法
ちなみに、プロビジョニングプロファイルの有効期限の期間自体を知るには、ExpirationDate
プロパティと同様に存在する、TimeToLive
というプロパティを取得すれば良い。
let timeToLive = plist["TimeToLive"] as! Int
print("有効期間", timeToLive) // 「7」が取れる
以上
今回のサンプルコードでは print()
しているだけだが、結果を画面に置いたテキストボックスなどに表示するようにすれば、アプリ上でも確認できるようになる。
コレで開発中のアプリを入れっぱなしにしていて「あっ期限切れてた」ということがなくなるだろう。