You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi all
~2 years experienced dev, new to Swift and GRDB
I am trying to setup a GRDB stack onto my app
My app is a dictionnary that will rely on a static database (basically all the words and translations) that will weigh ~200MB
I tried to follow the best practices as shown in the Demo Apps, and I ended up with an AppDatabase class that I call at the launch of my app and that handles the initialization of my database (run migrations + populates it). But it seems to me that it always run the migrations + the populateDb function at the launch of the app. This is not what I expect as it will take a lot of time for my app to open everytime...
I guess I could also preload an already existing database, but I am not sure...
Would I still be able to rely on the GRDB associationRelationships like hasMany, belongsTo like in my examples below ?
Could you give me the best practice to handle such matter ?
Here are my files that I simplified for this example, my database schema is way bigger and complex than that:
//
// Migration_01_CreateTables.swift
// GRDBPlayground
//
// Created by Léos on 28/07/2024.
//
import GRDB
structMigration_01_CreateTables{staticfunc performMigration(migrator:inoutDatabaseMigrator){
migrator.registerMigration("CreateTables"){ db in
// Create wordboxes table
try db.create(table:"wordboxes"){ t in
t.autoIncrementedPrimaryKey("id")
t.column("name",.text).notNull()}
// Create translations table
try db.create(table:"translations"){ t in
t.autoIncrementedPrimaryKey("id")
t.column("wordboxID",.integer).notNull().references("wordboxes")
t.column("text",.text).notNull()}}}}
//
// models.swift
// GRDBPlayground
//
// Created by Léos on 27/07/2024.
//
import Foundation
import GRDB
enumLanguage:String{case english ="en"case french ="fr"}structTranslation:Codable{varid:Int64?varwordboxID:Int64?vartext:String}extensionTranslation:FetchableRecord,MutablePersistableRecord{staticvardatabaseTableName:String{return"translations"}enumColumns:String,ColumnExpression{case id, wordboxID, text
}staticletwordbox=belongsTo(WordBox.self)varwordbox:QueryInterfaceRequest<WordBox>{returnrequest(for:Translation.wordbox)}mutatingfunc didInsert(with rowID:Int64, for column:String?){
id = rowID
}}structWordBox:Codable{varid:Int64?varname:String}extensionWordBox:FetchableRecord,MutablePersistableRecord{staticvardatabaseTableName:String{return"wordboxes"}enumColumns:String,ColumnExpression{case id, name
}staticlettranslations=hasMany(Translation.self)vartranslations:QueryInterfaceRequest<Translation>{returnrequest(for:WordBox.translations)}mutatingfunc didInsert(with rowID:Int64, for column:String?){
id = rowID
}}
//
// AppDatabase.swift
// GRDBPlayground
//
// Created by Léos on 27/07/2024.
//
import Foundation
import GRDB
import os.log
structAppDatabase{privateletdbWriter:anyDatabaseWriterinit(_ dbWriter:anyDatabaseWriter)throws{self.dbWriter = dbWriter
try migrator.migrate(dbWriter)}privatestaticletsqlLogger=OSLog(subsystem:Bundle.main.bundleIdentifier!, category:"SQL")publicstaticfunc makeConfiguration(_ base:Configuration=Configuration())->Configuration{varconfig= base
ifProcessInfo.processInfo.environment["SQL_TRACE"]!=nil{
config.prepareDatabase{ db in
db.trace{os_log("%{public}@", log: sqlLogger, type:.debug,String(describing: $0))}}}#if DEBUG
config.publicStatementArguments =true#endifreturn config
}privatevarmigrator:DatabaseMigrator{varmigrator=DatabaseMigrator()#if DEBUG
migrator.eraseDatabaseOnSchemaChange =true#endif
// Register migrations
Migration_01_CreateTables.performMigration(migrator:&migrator)return migrator
}}extensionAppDatabase{staticletshared=makeShared()privatestaticfunc makeShared()->AppDatabase{do{letfileManager=FileManager.default
letappSupportURL=try fileManager.url(
for:.applicationSupportDirectory, in:.userDomainMask,
appropriateFor:nil, create:true)letdirectoryURL= appSupportURL.appendingPathComponent("Database", isDirectory:true)try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories:true)letdatabaseURL= directoryURL.appendingPathComponent("db.sqlite")NSLog("Database stored at \(databaseURL.path)")letdbPool=tryDatabasePool(
path: databaseURL.path,
configuration:AppDatabase.makeConfiguration())letappDatabase=tryAppDatabase(dbPool)
// Populate the database if it is empty
// try appDatabase.populate()
return appDatabase
}catch{fatalError("Unresolved error \(error)")}}}extensionAppDatabase{varreader:DatabaseReader{
dbWriter
}}
//
// GRDBPlaygroundApp.swift
// GRDBPlayground
//
// Created by Léos on 27/07/2024.
//
import SwiftUI
@mainstructGRDBPlaygroundApp:App{init(){
// Initialize the shared database instance
_ =AppDatabase.shared
}varbody:someScene{WindowGroup{ContentView().environment(\.appDatabase,AppDatabase.shared)}}}structAppDatabaseKey:EnvironmentKey{staticletdefaultValue:AppDatabase=AppDatabase.shared
}extensionEnvironmentValues{varappDatabase:AppDatabase{get{self[AppDatabaseKey.self]}set{self[AppDatabaseKey.self]= newValue }}}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Hi all
~2 years experienced dev, new to Swift and GRDB
I am trying to setup a GRDB stack onto my app
My app is a dictionnary that will rely on a static database (basically all the words and translations) that will weigh ~200MB
I tried to follow the best practices as shown in the Demo Apps, and I ended up with an AppDatabase class that I call at the launch of my app and that handles the initialization of my database (run migrations + populates it). But it seems to me that it always run the migrations + the populateDb function at the launch of the app. This is not what I expect as it will take a lot of time for my app to open everytime...
I guess I could also preload an already existing database, but I am not sure...
Would I still be able to rely on the GRDB associationRelationships like hasMany, belongsTo like in my examples below ?
Could you give me the best practice to handle such matter ?
Here are my files that I simplified for this example, my database schema is way bigger and complex than that:
Beta Was this translation helpful? Give feedback.
All reactions