Kotlin Mutliplatform を利用して iOS 向けにもアプリを展開する際に、その中でも特に Widget も含む場合には App Group を考慮する必要があります。 iOS Widget データ共有の基本については以下の記事も参照ください。
Kotlin Multiplatform に対応したデータベースには、現在主に二つ候補があります。
- Room
- SQLDelight
key-value の保存形式で十分な場合は、 multiplatform-settings も候補になります。こちらについてはこの記事では扱いません。後述の参考記事に詳しい解説があります。
Room
Room は 2.7.0-alpha01
から Kotlin Multiplatform に対応しています。
詳しい実装は Google から公式のガイドが用意されています。
このガイドでは App Group には対応していないため、 getDatabaseBuilder
を書き換える必要があります。
// shared/src/iosMain/kotlin/Database.kt
fun getDatabaseBuilder(): RoomDatabase.Builder<AppDatabase> {
val dbFilePath = documentDirectory() + "/my_room.db"
return Room.databaseBuilder<AppDatabase>(
name = dbFilePath,
)
}
private fun documentDirectory(): String {
- val documentDirectory = NSFileManager.defaultManager.URLForDirectory(
+ val documentDirectory = NSFileManager.defaultManager.containerURLForSecurityApplicationGroupIdentifier(
+ groupIdentifier = "APP_GROUP_IDENTIFIER",
- directory = NSDocumentDirectory,
- inDomain = NSUserDomainMask,
- appropriateForURL = null,
- create = false,
- error = null,
)
return requireNotNull(documentDirectory?.path)
}
NSFileManager
を利用するのは変わらないですが、 URLForDirectory
ではなく、 containerURLForSecurityApplicationGroupIdentifier
で APP_GROUP
を指定して、アプリ間で共有可能なディレクトリを取得します。
SQLDelight
SQLDelight を利用した公式のガイドは JetBrains から提供されています。
こちらのガイドも App Group には対応していないため、 createDriver
を書き換える必要があります。
// shared/src/iosMain/kotlin/DatabaseDriverFactory.kt
class IOSDatabaseDriverFactory : DatabaseDriverFactory {
override fun createDriver(): SqlDriver {
- return NativeSqliteDriver(AppDatabase.Schema, "launch.db")
+ return NativeSqliteDriver(
+ name = "launch.db",
+ version = AppDatabase.Schema.version.toInt(),
+ extendedConfig = DatabaseConfiguration.Extended(
+ basePath = NSFileManager
+ .defaultManager
+ .containerURLForSecurityApplicationGroupIdentifier(
+ groupIdentifier = "APP_GROUP_IDENTIFIER"
+ )?.absoluteString
+ )
}
}
方針としては Room と同様に、containerURLForSecurityApplicationGroupIdentifier
で APP_GROUP
を指定して、アプリ間で共有可能なディレクトリを取得します。
DatabaseConfiguration.Extended
を介してそのパスを渡すようにします。
以下の Issue で会話されていました。
Room の DatabaseConfiguration
よりも拡張された API が SQLDelight では提供されていました。
参考
SQLDelight の App Group の指定は Kotlin Multiplatform で App Clip に対応した以下の記事が大変参考になりました。 key-value 形式の multiplatform-settings の解説も含まれています。
注意点
Xcode の Signing & Capabilities では App Group が省略表示されている可能性があります
引き継いだり途中参画するプロジェクトにおいて、自身で作成していない App Group を確認する際は注意が必要です。
例えば、次のように表示されたりします。
ここでの正式名称は group.com.example.long.long.long.app.group.name
です。 entitlements
から正しい App Group を参照できます。
まとめ
たったこれだけのことで Kotlin Multiplatform で保存したデータを iOS 側の App と Widget でも共有できるようになります!
- App Group を定義する
- App Group を指定したパスにデータベースファイルを作成する