前回までで一通りAppExtensionから収容アプリケーションまで、コンテンツとしてString型のデータを受け渡しました。今回はAppExtensionとは直接関係ありませんが、データのシリアライズについて書いておこうと思います。
ここまでのサンプルでは、AppExtensionでコンテンツを保存して、収容アプリケーションの起動時に取得していました。
AppExtensionから複数のデータを受け渡したいこともあります。もちろん、UserDefaultのキーをそれぞれ振って、独立したデータとして扱うのもありですが、意味のあるまとまりのデータであれば、構造体やクラスにしてシリアライズして使いたいところです。
そこで、今回はContentsという構造体を作ってみました(ちなみにクラスでも同様です)。
import UIKit
struct Contents: Codable {
// MARK: - PROPERTY
var key: Int //何かのキー
var text: String //内容
var date: Date //日付
// MARK: - INITIALIZER
init() {
self.key = 0 //何かのキー
self.text = "" //内容
self.date = Date() //作成日付
}
init(key: Int, text: String, date: Date) {
self.key = key //何かキー
self.text = text //内容
self.date = date //日付
}
}
自動でエンコード、デコードできる、Codableというプロトコルがポイントです。Contents構造体がCodableを備えているのはもちろんですが、中に含まれるプロパティーもCodableである必要があります。
Contents構造体の中にInt型, String型, Date型のプロパティーがありますが、これらの型はすべてデフォルトでCodableなので問題ありません。
このContents.swiftを収容アプリケーションの中に作成します。そしてこのソースにAppExtensionからもアクセスできるように、AppExtensionのTargetのBuild PhasesのCompile Sourcesに指定します。
両方に同じソースを作る必要はありませんからね。 |
これでContents型が収容アプリケーション、AppExtensionの両方から使用できるようになりました。あとはエンコード・デコードしてUserDefaultに保存・取り出しをします。
AppExtensionでは、Contents型をData型にエンコードしてから、UserDefaultに格納します。
/// コンテンツをApp Groupのユーザーデフォルトに保存
///
/// - Parameter content:
private func saveContent(content: String) {
guard let userDefaults = UserDefaults.init(suiteName: "group.jp.blowbend.ios.test.AwesomeApp") else {
print("userdefault: app group suite name is nil")
return
}
let contents = Contents(key: 123, text: content, date: Date())
do {
let data = try JSONEncoder().encode(contents) //Data型に変換
userDefaults.set(data, forKey: "user default key content") //データを保存
userDefaults.synchronize()
} catch {
print("userdefault: contents encode error!!")
}
}
収容アプリケーションでは、UserDefaultからData型で取得してから、Contents型にデコードします。
/// App Groupのユーザーデフォルトからコンテンツを取得
private func getContentFromAppGroup() {
guard let userDefaults = UserDefaults.init(suiteName: "group.jp.blowbend.ios.test.AwesomeApp") else {
print("userdefault: app group suite name is nil")
return
}
guard let content = userDefaults.object(forKey: "user default key content") ?? nil else {
print("userdefault: no content")
return
}
guard let data = content as? Data else {
print("userdefault: no data")
return
}
do {
let content = try JSONDecoder().decode(Contents.self, from: data)
print("content.key =\(content.key)")
print("content.text=\(content.text)")
print("content.date=\(content.date)")
} catch {
print("userdefault: JSONDecoder decode error")
}
userDefaults.removeObject(forKey: "user default key content") //無条件でデータの削除
}
これで、構造体をシリアライズしての受け渡しはOKです。
今回はここまで。
「使ってみた(App Extension編) おまけ」に続きます。
♪♪♪
こちらもどうぞ。
使ってみた(App Extension編) その1
使ってみた(App Extension編) その2
使ってみた(App Extension編) その3
使ってみた(App Extension編) その4
使ってみた(App Extension編) おまけ