1

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!

Ted Henry
  • 1,442
  • 1
  • 14
  • 34
  • mention your error description which are appear while database connection. – KKRocks Oct 19 '16 at 05:09
  • Share some of your code please – Jitendra Modi Oct 19 '16 at 05:20
  • @KKRocks I think there is only a very small chance connecting to the database will fail. If the connecting to the database does fail, the app is essentially useless. Showing the user something like "Fatal Error: Could not connect to database." would be appropriate. – Ted Henry Oct 19 '16 at 05:22
  • share some code for your database connection ? – KKRocks Oct 19 '16 at 05:29
  • @Jecky I've added the code for the first option. The second and third options are just general approach ideas which may not even be worth anything. I'm new to iOS programming and wonder how this surely common problem is usually handled. – Ted Henry Oct 19 '16 at 05:32
  • @KKRocks code added above – Ted Henry Oct 19 '16 at 05:33
  • I think You r missing one "/" before your database name in appending string @TedHenry. Try to add it and check – Jitendra Modi Oct 19 '16 at 05:35
  • @Jecky That part seems to work. The issue I'm concerned with is something like if the call to Connection fails for some unexpected reason (e.g. storage is completely full and a new database file cannot be created). I want to know how to gracefully handle an unexpected situation. I don't want to add an empty `catch{}` and pretend like the problem can never happen. :-) – Ted Henry Oct 19 '16 at 05:41
  • @TedHenry For that You can use Alertview instead of AlertController, You can directly show alertview, meanwhile Alertcontroller Requires to be present on view. You can show alerview within anywhere in project without presenting. – Jitendra Modi Oct 19 '16 at 05:48
  • @Jecky Seems like `UIAlertView` is no more. "In apps that run in versions of iOS prior to iOS 8, use the UIAlertView class to display an alert message to the user." - https://developer.apple.com/reference/uikit/uialertview – Ted Henry Oct 19 '16 at 05:50
  • @TedHenry Yeah, I know Alerview is deprecated but you can still use it – Jitendra Modi Oct 19 '16 at 05:51
  • @Jecky I'd like to know how to handle this in a way that will be supported going forward. :-) – Ted Henry Oct 19 '16 at 05:53
  • @TedHenry You can show alertcontroller upon window without needed of viewcontroller. Check this http://stackoverflow.com/questions/26554894/how-to-present-uialertcontroller-when-not-in-a-view-controller – Jitendra Modi Oct 19 '16 at 05:54
  • @Jecky Thank you. What a convoluted workaround! – Ted Henry Oct 19 '16 at 06:15
  • @TedHenry Its working or not for you ? If then please reply me, I will give you another suggestion – Jitendra Modi Oct 19 '16 at 06:19
  • @Jecky There is good reason for Apple depreciating `UIAlertView`. Objects and functions away from the view layer (e.g. utility functions) should `throw`. They should not present anything to the user. I don't want to work around that idea as it is actually a good idea. I'm leaning strongly towards my third option anyway. – Ted Henry Oct 19 '16 at 21:34

0 Answers0