2015-09-17 11 views
6

物理的なiPhoneにビルド済みのSQLiteデータベース(FMDBラッパー付き)を含めることを試みています。ただし、事前設定されたデータベースは、物理デバイスへのビルドに含まれていません。Swift - SQLiteデータベースがデバイスに組み込まれていない

IOSシミュレータでは正常に動作しますが、1台のシミュレータデバイスでのみ動作することに注意してください。

ビルドフェーズ>バンドルされたリソースをコピーし、ライブラリとリンクバイナリの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. 
    } 
} 

をUPDATE - XCodeの7におけるワーキングスイフト2コード - 物理デバイスOKにコピーFMDBラッパーを使用して、事前にSQLiteデータベース:

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

私の質問はなぜ投票されましたか? – IlludiumPu36

+0

ダウン投票者はコメントを残さなかったので、私は反対投票にアップしました。 –

答えて

2

何Iからドキュメントフォルダ内のファイルにアクセスするので、どのシミュレータ/デバイスでも動作しないはずです。あなたのバンドルにはありません。あなたが何をする必要があるか

があり、それを開こうとする前に、ドキュメントディレクトリにバンドルからファイルをコピーします:

//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) 
+0

@ Daij-Djan ... upvoteに感謝します! Xcodeは、エラービットを含めるために以下の変更を望んでいました:filemgr.copyItemAtPath(bundleDatabasePath、toPath:databasePath、error:nil)しかし、 "NSStringは暗黙的に 'String'に変換できません;明示的に変換する? – IlludiumPu36

+0

swift 1.2と2を切り替えると上記のコードは1.2ですがエラーは2.0です - databasePathは決してNSStringではありません:) –

+0

多分XCodeが問題です...私はv6.4を使用しています。 – IlludiumPu36

2

私は同様の問題がありました。具体的には、iPhoneシミュレータで作業しているアプリケーションにデータを追加した後、そのデータをすべて私の物理的なiPhoneデバイスに再度追加する必要はありませんでした。

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 _ { 
     } 
    } 
} 
:IlludimPu36とDaij-Djanが提供するソリューションを見た後、私はアプリケーションデリゲートの(AppDelegate.swift)アプリケーション(didFinishLaunchingWithOptions)メソッドからの非常に最初の行に呼んで、次のような方法を思い付きました

これはうまくいくように見え、デバッガでメソッドの各行をステップ実行すると、データベースがまだ存在しない場合(つまり、アプリケーションを削除した後や新規にインストールした後、またはシミュレータをリセットした場合)データベースがすでに存在している場合です。物理的なデバイスでも同じ結果が得られます。

これにヒント/答えを提供してくれてありがとう@ IlludiumPu36と@ Daij-Djan、これが他の誰かを助けることを願っています。

関連する問題