Swift - предварительно заполненная база данных SQLite не включена в устройство

Я пытаюсь включить предварительно заполненную базу данных SQLite (с оболочкой FMDB) в сборку моего физического iPhone. Однако предварительно заполненная база данных не включается в сборку физического устройства.

Обратите внимание, что он отлично работает в симуляторе IOS, но только для одного симулятора.

Я включил базу данных в «Фазы сборки»> «Копировать связанные ресурсы» и связал libsqlite3.dylib в разделе «Связать двоичный файл с библиотеками».

Какой код 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.
    }
}

ОБНОВЛЕНИЕ - Рабочий код Swift 2 в XCode 7 - предварительно заполненная база данных SQLite с использованием оболочки FMDB, скопированная на физическое устройство. ОК:

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.
    }
}

person IlludiumPu36    schedule 17.09.2015    source источник
comment
Почему мой вопрос был отклонен ????   -  person IlludiumPu36    schedule 17.09.2015
comment
Голосующий вниз не оставил комментариев, поэтому я проголосовал против.   -  person Daij-Djan    schedule 17.09.2015


Ответы (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)
person Daij-Djan    schedule 17.09.2015
comment
@ Daij-Djan ... спасибо за голос! XCode хотел изменить следующее, чтобы включить бит ошибки: filemgr.copyItemAtPath (bundleDatabasePath, toPath: databasePath, error: nil), но теперь я получаю, что NSString не может быть неявно преобразован в 'String'; вы имели в виду 'как', чтобы явно конвертировать? - person IlludiumPu36; 17.09.2015
comment
вы переключаетесь между быстрым 1.2 и 2 - ваш код выше 1.2, но ошибка 2.0 - databasePath никогда не должен быть NSString :) - person Daij-Djan; 17.09.2015
comment
Может проблема в XCode ... Я использую v6.4. - person IlludiumPu36; 17.09.2015
comment
yip - его больше нет, в xcode 7 есть swift 2, так что да - вам нужно использовать здесь и там - person Daij-Djan; 17.09.2015
comment
Я решил обновить XCode до v7 и использовать Swift 2. Теперь stringByAppendingPathComponent был удален из Swift 2 и заменен на URLByAppendingPathComponent, который выдает значение ошибки типа «String», не имеет члена «URLByAppendingPathComponent». Есть идеи? - person IlludiumPu36; 21.09.2015
comment
Спасибо, проблема решена. Другой - filemgr.copyItemAtPath (bundleDatabasePath, toPath: databasePath) имеет ошибку и ожидает оператора try. Теперь это приводит к фатальной ошибке: {попробуйте filemgr.copyItemAtPath (bundleDatabasePath !, toPath: databasePath)} catch _ {//} - person IlludiumPu36; 21.09.2015
comment
Фатальной ошибкой была фатальная ошибка: неожиданно обнаружен ноль при разворачивании необязательного значения (lldb) - person IlludiumPu36; 21.09.2015
comment
Также есть ошибка в строке try filemgr.copyItemAtPath (bundleDatabasePath !, toPath: databasePath) Поток 1: EXC_BAD_INSTRUCTION (code = EXC_1386_invop, SUBCODE = 0X0) - person IlludiumPu36; 21.09.2015
comment
вы никогда не добавляли его в цель, или он имеет другое имя или находится в подпапке - person Daij-Djan; 21.09.2015

У меня была аналогичная проблема; в частности, после добавления данных в приложение, над которым я работаю в симуляторе 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 за советы / ответы на этот вопрос, и я надеюсь, что это поможет кому-то другому.

person William L. Marr III    schedule 26.01.2016