Swift - 设备上未包含预先填充的SQLite数据库

时间:2015-09-17 05:00:32

标签: swift sqlite fmdb

我正在尝试将一个预先填充的SQLite数据库(带有FMDB包装器)包含在我的物理iPhone的构建中。但是,预先填充的数据库未包含在物理设备的构建中。

请注意,它在IOS模拟器中工作正常,但仅适用于一个模拟器设备。

我已将数据库纳入Build Phases>复制捆绑资源并将Link Binary下的libsqlite3.dylib与Libraries联系起来。

我需要添加什么Swift代码才能将构建中包含的数据库提供给物理设备?

代码:

import UIKit

class ViewController: UIViewController {


    @IBOutlet weak var checkButton: UIButton!
    @IBOutlet weak var tests_scroller: UITextView!

    var databasePath = NSString()

    override func viewDidLoad() {
        super.viewDidLoad()

        checkButton.setTitle("\u{2610}", forState: .Normal)
        checkButton.setTitle("\u{2611}", forState: .Selected)


        let filemgr = NSFileManager.defaultManager()

        let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)

        let docsDir = dirPaths[0] as! String

        databasePath = docsDir.stringByAppendingPathComponent("vmd_db.db")

        let myDatabase = FMDatabase(path: databasePath as String)


        if myDatabase.open(){

            var arrayData:[String] = []

            let query_lab_test = "SELECT lab_test FROM lab_test ORDER BY lab_test ASC"

            let results_lab_test:FMResultSet? = myDatabase.executeQuery(query_lab_test, withArgumentsInArray: nil)

            while results_lab_test?.next() == true {

                if let resultString = results_lab_test?.stringForColumn("lab_test"){

                arrayData.append(resultString)

            }
        }
            var multiLineString = join("\n", arrayData)
            tests_scroller.text = multiLineString
            myDatabase.close()
    }
    }




    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

UPDATE - 在XCode 7中使用Swift 2代码 - 使用FMDB包装器预先填充的SQLite数据库复制到物理设备OK:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tests_scroller: UITextView!

    var databasePath = NSString()

    override func viewDidLoad() {
        super.viewDidLoad()


        let sourcePath = NSBundle.mainBundle().pathForResource("vmd_db", ofType: "db")

        let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String!

        let destinationPath = (documentDirectoryPath as NSString).stringByAppendingPathComponent("vmd_db.db")

        do {                                
            try NSFileManager().copyItemAtPath(sourcePath!, toPath: destinationPath)

        } catch _ {                
        }

        //read it
        let myDatabase = FMDatabase(path: destinationPath as String)

        if myDatabase.open(){

            var arrayData:[String] = []

            let query_lab_test = "SELECT lab_test FROM lab_test ORDER BY lab_test ASC"

            let results_lab_test:FMResultSet? = myDatabase.executeQuery(query_lab_test, withArgumentsInArray: nil)

            while results_lab_test?.next() == true {

                if let resultString = results_lab_test?.stringForColumn("lab_test"){

                    arrayData.append(resultString)

                }
            }

            let multiLineString = arrayData.joinWithSeparator("\n")

            tests_scroller.text = multiLineString
            myDatabase.close()
        }
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

2 个答案:

答案 0 :(得分:2)

从我看到它不应该在任何模拟器/设备上工作,因为您访问文档文件夹中的文件。那不在你的包中。

您需要做的是将文件从包中复制到文档目录,然后尝试在那里打开它:

//path in documents
let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docsDir = dirPaths[0]
databasePath = docsDir.stringByAppendingPathComponent("vmd_db.db")

//if not there, copy from bundle
if !filemgr.fileExistsAtPath(databasePath) {
    let bundleDatabasePath = NSBundle.mainBundle().pathForResource("vm_db", ofType: "db")
    filemgr.copyItemAtPath(bundleDatabasePath, toPath: databasePath)
}

//read it
let myDatabase = FMDatabase(path: databasePath as String)

答案 1 :(得分:2)

我有类似的问题;特别是,在将数据添加到我正在iPhone模拟器中处理的应用程序之后,我不想再将所有这些数据添加到我的物理iPhone设备中。在查看了IlludimPu36和Daij-Djan提供的解决方案之后,我提出了以下方法,我在App Delegate(AppDelegate.swift)应用程序(didFinishLaunchingWithOptions)方法的第一行调用:

func copyBundledSQLiteDB() {
    let sourcePath = NSBundle.mainBundle().pathForResource("filename", ofType: "sqlite")

    let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String!

    let destinationPath = (documentDirectoryPath as NSString).stringByAppendingPathComponent("filename.sqlite")

    // If file does not exist in the Documents directory already,
    // then copy it from the bundle.
    if !NSFileManager().fileExistsAtPath(destinationPath) {
        do {
            try NSFileManager().copyItemAtPath(sourcePath!, toPath: destinationPath)

        } catch _ {
        }
    }
}

它似乎工作,并且在数据库尚未存在时(即,在删除应用程序或重置模拟器之后的全新安装之后),逐步调试调试器中方法的每一行看起来都没有错误),当数据库已经存在时。我也在物理设备上得到了相同的结果。

感谢@ IlludiumPu36和@ Daij-Djan为此提供提示/答案,我希望这可以帮助其他人。