Search code examples
swift3xcode8fmdb

FMDB & Swift, " Optional("no such table: Student info") " in real device but it can be done in simulator


I'm newbie, plz help me to solve this out, I still have lots of other things to work on, really thank you thank you very much!

This is a further question after How to use FMDB on the generic iOS device instead of simulator? When I execute the app on my device and the error threw out: "no such table: Student info", I've print all the path and they all pointed to the same file so I assumed the database has already copied? Console shows like this:

file:///var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/
file:///var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
/var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
file:///var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/
file:///var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
/var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
/var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
<NSFileManager: 0x17401c1b0>
2017-03-13 16:43:25.446039 Test1.3[16360:5045427] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2017-03-13 16:43:25.457278 Test1.3[16360:5045427] [MC] Reading from public effective user settings.
Insert failed:
Optional("no such table: Student info")

The Data.db is in my bundle resources in target; and the contents in my device is a blank Data.db;

The 2nd question: If you look at the Utility.Swift in the previous question, although the app works good on simulator but after it was loaded, there should be an alertView said "Your database copy successfully", but it didn't. Following is that part of the code:

    class func copyFile(_ fileName: NSString){

    let dbPath: String = getPath(fileName as String)
    let fileManager = FileManager.default

    print(dbPath)
    print(fileManager)

    if !fileManager.fileExists(atPath: dbPath) {
        let documentsURL = Bundle.main.resourceURL
        let fromPath = documentsURL!.appendingPathComponent(fileName as String)

        var error : NSError?
        do {
            try fileManager.copyItem(atPath: fromPath.path, toPath: dbPath)
        }
        catch let error1 as NSError {
            error = error1
        }
        if(error != nil){
            self.invokeAlertMethod("Error Occured", strBody: "\(error?.localizedDescription)" as NSString, delegate: nil)
        }
        else{
            self.invokeAlertMethod("Successed", strBody: "Your database copy successfully", delegate: nil)
        }
    }
} 

Solution

  • Okay for answering this question I went through your demo.

    Where I found couple of mistakes. Let me go through one by one.

    1) Your class Utility have a getPath method. What it does it will keep copying db every time although db is already present in documents directory and your documents directory db will be replaced with the sample structure. You should always check that if db is already present in documents directory or not.

    2) Your db was getting copied into documents directory but structure wasn't. There was no Student info table in db of documents directory.

    3) Please avoid using space or any special characters in table names.

    So what I did just corrected your method getPath in utility class.

    Please replace your method with this one

    class func getPath(_ fileName: String) -> String {
    
             let bundlePath = Bundle.main.path(forResource: "Data", ofType: ".db")
             let destPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
             let fileManager = FileManager.default
             let fullDestPath = URL(fileURLWithPath: destPath).appendingPathComponent("Data.db")
             if fileManager.fileExists(atPath: fullDestPath.path){
                print("Database file is exist")
                print(fileManager.fileExists(atPath: bundlePath!))
             }else{
                do{
                    try fileManager.copyItem(atPath: bundlePath!, toPath: fullDestPath.path)
                }catch{
                    print("\n",error)
                }
             }
    
            print(fullDestPath.path)
            return fullDestPath.path
    }
    

    After changing this piece of code I tried to run in my device and inserted couple of records.

    Let me know if you have any more questions.

    If you find this answer helpful just accept it.