-3

Am just starting to use SQLite in Swift and am running into a declaration problem. I would like to wrap everything in one class that I can then call methods on.

My problem is I don't know how to declare db so that when I do call Connect, it can be filled in an always be available while the class exists. I could call connect at the init, but I don't want to call Connect until I need it. When I code it as below I get the following error:

Return from initializer without initializing all stored properties

class MySQL {
    var db : Connection
    var dbPath : String
    
    init() {
        dbPath = getDocumentsDirectory().absoluteString + "db.sqlite3"
    }
    
    func open(){
        do{
            db = try Connection(dbPath)}
        catch{}

        let users = Table("users")
        print(users)
    }
}
LuisC329
  • 131
  • 8

2 Answers2

4

You probably want to use lazy property.

A lazy stored property is a property whose initial value isn’t calculated until the first time it’s used. You indicate a lazy stored property by writing the lazy modifier before its declaration.

class MySQL {
    lazy var db : Connection = {
        // Make initialisation here 
    }()
    var dbPath : String

    ...
}

More information you can read from official docs.

  • Whenever I use this i get get an error `Cannot convert value of type '()' to closure result type 'Connection'`. Have you tested the code? – MrinmoyMk Jul 02 '21 at 22:38
  • @MrinmoyMk Looks like you don't complete the return statement in the closure. If the closure is empty, you will see this error. Probably, this is the reason. – Yura Reutskiy Jul 05 '21 at 15:16
0

I could call connect at the init, but I don't want to call Connect until I need it.

Absolutely right! Don't do anything like that in init.

Just rewrite your declaration to make the Connection nil, precisely as you suggested:

class MySQL {
    var db : Connection? = nil
    var dbPath : String
    
    init() {
        dbPath = getDocumentsDirectory().absoluteString + "db.sqlite3"
    }
    
    func open(){
        do{
            db = try Connection(dbPath)}
        catch{}

        let users = Table("users")
        print(users)
    }
}

The consequence is that whenever you talk to self.db from now on, except in order set it, you will have to check whether it is nil. You can use Optional chaining to do that painlessly. You could avoid that by declaring db as Connection! instead of Connection? but that risks a later crash and I can't recommend it.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I should add: there are a lot of great SQLite front end libraries and you could save yourself a lot of work by just using one. – matt May 09 '21 at 04:03
  • Thank you, this was it. I was trying nil, but without the ?. – LuisC329 May 10 '21 at 01:19