1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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 ではなく、 containerURLForSecurityApplicationGroupIdentifierAPP_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 と同様に、containerURLForSecurityApplicationGroupIdentifierAPP_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 を確認する際は注意が必要です。

例えば、次のように表示されたりします。

スクリーンショット 2024-12-19 2.19.57.png

ここでの正式名称は group.com.example.long.long.long.app.group.name です。 entitlements から正しい App Group を参照できます。

スクリーンショット 2024-12-19 2.20.21.png

まとめ

たったこれだけのことで Kotlin Multiplatform で保存したデータを iOS 側の App と Widget でも共有できるようになります!

  • App Group を定義する
  • App Group を指定したパスにデータベースファイルを作成する
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?