Originally created by @ghost on GitHub (Jan 12, 2017).
Hi,
In my app I have to populate my database with external data. I'm doing that during the app launch. This could take a lot of time, because there are thousands of records returned from the server. To avoid bad UX, making user to wait, I'm preloading data like this:
class AppDelegate: UIResponder, UIApplicationDelegate {
...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
...
// Preload SQLite, for better UX
preloadData()
// Setup Core Data
let dataStack = DataStack(modelName: "Compare")
CoreStore.defaultStack = dataStack
try! CoreStore.addStorageAndWait()
...
return true
}
...
}
...
extension AppDelegate {
//MARK: - Helpers
fileprivate lazy var applicationSupportDirectory: URL = {
let urls = FileManager.default.urls(for: .applicationSupportDirectory,
in: .userDomainMask)
return urls.first!
}()
// same as defaultRootDirectory in SQLiteStore
fileprivate lazy var sqliteStoreDefaultRootDirectory: URL = {
let urls = FileManager.default.urls(for: .applicationSupportDirectory,
in: .userDomainMask)
let defaultSystemDirectory = self.applicationSupportDirectory
return defaultSystemDirectory.appendingPathComponent(
Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack",
isDirectory: true
)
//MARK: - Preload CoreData
func preloadData() {
let fileManager = FileManager.default
// Exception Means that is already created - we don't cate
try! fileManager.createDirectory(at: sqliteStoreDefaultRootDirectory,
withIntermediateDirectories: true,
attributes: nil)
let url = sqliteStoreDefaultRootDirectory.appendingPathComponent("Compare.sqlite")
if !fileManager.fileExists(atPath: url.path) {
// !!! Add wal and shm if needed
let sourceSqliteURLs = [Bundle.main.url(forResource: "Compare",
withExtension: "sqlite")!]
let destSqliteURLs = [url]
do {
for index in 0..<sourceSqliteURLs.count {
try fileManager.copyItem(at: sourceSqliteURLs[index],
to: destSqliteURLs[index])
}
} catch {
print("Preload Data Error: \(error)")
}
}
}
}
As you can see I'm repeating the part of your code responsible for getting the default root directory (see: sqliteStoreDefaultRootDirectory). Is it possible for you to make those methods accessible? Or even better, how about implementing a method which will copy bundled database (.wal and .shm also) to store.
Originally created by @ghost on GitHub (Jan 12, 2017).
Hi,
In my app I have to populate my database with external data. I'm doing that during the app launch. This could take a lot of time, because there are thousands of records returned from the server. To avoid bad UX, making user to wait, I'm preloading data like this:
```
class AppDelegate: UIResponder, UIApplicationDelegate {
...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
...
// Preload SQLite, for better UX
preloadData()
// Setup Core Data
let dataStack = DataStack(modelName: "Compare")
CoreStore.defaultStack = dataStack
try! CoreStore.addStorageAndWait()
...
return true
}
...
}
...
extension AppDelegate {
//MARK: - Helpers
fileprivate lazy var applicationSupportDirectory: URL = {
let urls = FileManager.default.urls(for: .applicationSupportDirectory,
in: .userDomainMask)
return urls.first!
}()
// same as defaultRootDirectory in SQLiteStore
fileprivate lazy var sqliteStoreDefaultRootDirectory: URL = {
let urls = FileManager.default.urls(for: .applicationSupportDirectory,
in: .userDomainMask)
let defaultSystemDirectory = self.applicationSupportDirectory
return defaultSystemDirectory.appendingPathComponent(
Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack",
isDirectory: true
)
//MARK: - Preload CoreData
func preloadData() {
let fileManager = FileManager.default
// Exception Means that is already created - we don't cate
try! fileManager.createDirectory(at: sqliteStoreDefaultRootDirectory,
withIntermediateDirectories: true,
attributes: nil)
let url = sqliteStoreDefaultRootDirectory.appendingPathComponent("Compare.sqlite")
if !fileManager.fileExists(atPath: url.path) {
// !!! Add wal and shm if needed
let sourceSqliteURLs = [Bundle.main.url(forResource: "Compare",
withExtension: "sqlite")!]
let destSqliteURLs = [url]
do {
for index in 0..<sourceSqliteURLs.count {
try fileManager.copyItem(at: sourceSqliteURLs[index],
to: destSqliteURLs[index])
}
} catch {
print("Preload Data Error: \(error)")
}
}
}
}
```
As you can see I'm repeating the part of your code responsible for getting the default root directory (see: `sqliteStoreDefaultRootDirectory`). Is it possible for you to make those methods accessible? Or even better, how about implementing a method which will copy bundled database (.wal and .shm also) to store.
adam
added the question label 2025-12-29 18:23:12 +01:00
If you trace the contents of addStorageAndWait(), you'll find that it just passes a default-initialized SQLiteStore. You can get the actual path from that instance:
@JohnEstropia commented on GitHub (Jan 13, 2017):
Hi, thanks for the feedback!
If you trace the contents of `addStorageAndWait()`, you'll find that it just passes a default-initialized `SQLiteStore`. You can get the actual path from that instance:
```swift
let storage = SQLiteStore()
let sqliteStoreDefaultRootDirectory = storage.fileURL
// ... preloadData(sqliteStoreDefaultRootDirectory)
try! CoreStore.addStorageAndWait(storage)
```
You can also do it the other way: specify your own path and assign it to `SQLiteStore()`
```swift
let sqliteStoreDefaultRootDirector: URL = // ...
let storage = SQLiteStore(fileURL: sqliteStoreDefaultRootDirector)
// ... preloadData(sqliteStoreDefaultRootDirectory)
try! CoreStore.addStorageAndWait(storage)
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @ghost on GitHub (Jan 12, 2017).
Hi,
In my app I have to populate my database with external data. I'm doing that during the app launch. This could take a lot of time, because there are thousands of records returned from the server. To avoid bad UX, making user to wait, I'm preloading data like this:
As you can see I'm repeating the part of your code responsible for getting the default root directory (see:
sqliteStoreDefaultRootDirectory). Is it possible for you to make those methods accessible? Or even better, how about implementing a method which will copy bundled database (.wal and .shm also) to store.@JohnEstropia commented on GitHub (Jan 13, 2017):
Hi, thanks for the feedback!
If you trace the contents of
addStorageAndWait(), you'll find that it just passes a default-initializedSQLiteStore. You can get the actual path from that instance:You can also do it the other way: specify your own path and assign it to
SQLiteStore()@ghost commented on GitHub (Jan 13, 2017):
Thank you very much, I totally missed that!