When my iOS app starts, I want to connect to a local SQLite database using SQLite.swift and then show the user a list of items that are stored in the database. Making the database connection can throw
. If connecting fails then I want to show the user a nice error message.
In Main.storyboard
, my root view controller is a UINavigationController
. The navigation controller's root/top view controller is a UIViewController
that contains a UITableView
to display the items in the database.
My first idea was to connect to the database in AppDelegate
's application(_:didFinishLaunchingWithOptions:)
and somehow present a UIAlertController
over the UIViewController
. I cannot seem to get the UIViewController
to present the UIAlertController
. Even if I could, I'm starting to doubt this approach because if the items cannot be loaded from the database then the table will fail to render under the alert anyway. What I was working towards was something like this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
do {
let documentsDirectories = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = documentsDirectories.first!
let dbPath = documentsDirectory.appendingPathComponent("db.sqlite3")
let db = try Connection("\(dbPath)")
// ...
}
catch {
let navController = window!.rootViewController as! UINavigationController
let itemsController = navController.topViewController as! ItemsController
let failureAlert = UIAlertController(
title: "Fatal Error",
message: "Could not connect to the database.",
preferredStyle: .alert)
itemsController.present(failureAlert, animated: true, completion: nil)
}
//...
}
My second idea is still to connect to the database in AppDelegate
's application(_:didFinishLaunchingWithOptions:)
. If that throws then change the window's root view to an error view that the user will see. This way the table that displays the items will never even try to display the items.
My third idea is to make AppDelegate
much lazier and punt the problem down the line. Just create a data access object that knows the path to the SQLite database file. Pass the dao to the UIViewController
which acts as a data source for the UITableView
. When the data source needs info from the database the first time, have the dao attempt to connect (and migrate the database schema if necessary, etc) and let it throw
at that point. The UITableView
probably needs to be ready for a throw
when accessing data even if the dao has already connected to the database.
Any experience you can share for handling this gracefully?
Thanks!