Search code examples
iosswiftsqlitesqlite.swift

Why does my app create a zero byte database in the documents directory?


I deleted my app and run it again via Xcode. There were no files in the documents directory so I could copy my 32 byte SQLite file with tables in it from the main bundle.

After I deleted it, it creates a zero byte SQLite file if there's no file in the documents directory. So in the appdelegate it says correctly that it's there though it's not the file I want. If in iTunes I delete the file it copies the right file. This happens both in the emulator and on the device. Xcode 10.1 and Swift 4.2:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    Fabric.with([Crashlytics.self])

    let sourcePath = Bundle.main.path(forResource: "mydb", ofType: "db")!
    let fileManager = FileManager.default
    let doumentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
    let destinationPath = doumentDirectoryPath.appendingPathComponent("mydb")
    if !fileManager.fileExists(atPath: destinationPath) {
        do {
            try fileManager.copyItem(atPath: sourcePath, toPath: destinationPath)
        }
        catch
        {
            os_log("error copying database")
            Crashlytics.sharedInstance().recordError(error)
            print(error)
        }

    }

    return true
}

Code that opens the file:

import Foundation
import SQLite
import os.log

 var connected: Bool
//MARK: - private attributes
var db: Connection?

//MARK: - constructor
init() {
    let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
    do {
        db = try Connection("\(path)/mydb.db")
        connected = true
    }
    catch {
        connected = false
    }
}

Solution

  • Sqlite.swift constructor to the Connection method:

    /// Initializes a new SQLite connection.
    ///
    /// - Parameters:
    ///
    ///   - location: The location of the database. Creates a new database if it
    ///     doesn’t already exist (unless in read-only mode).
    ///
    ///     Default: `.inMemory`.
    ///
    ///   - readonly: Whether or not to open the database in a read-only state.
    ///
    ///     Default: `false`.
    ///
    /// - Returns: A new database connection.
    public init(_ location: SQLite.Connection.Location = default, readonly: Bool = default) throws
    

    It creates the database blank with no tables if it does not exists so I changed it:

    //MARK: - constructor
    init() {
        let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
        do {
            let sourcePath = Bundle.main.path(forResource: "mydb", ofType: "db")!
            let fileManager = FileManager.default
            let doumentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
            let destinationPath = doumentDirectoryPath.appendingPathComponent("mydb.db")
            if !fileManager.fileExists(atPath: destinationPath) {
                try fileManager.copyItem(atPath: sourcePath, toPath: destinationPath)
            }
    
            db = try Connection("\(path)/mydb.db")
            connected = true
        }
        catch {
            connected = false
        }
    }
    

    and it works.