2016-11-30 8 views
1

Swiftで単純なsqliteデータベースを作成しようとしていますが、テーブルを作成しようとするとエラー(特にSQLITE_ERROR)が表示されます。 SqliteをがCocoapod経由含まれSwift Sqlite SQLエラー

 var db :OpaquePointer? 
     let dbPath = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) 
      .appendingPathComponent("\(Date.init().timeIntervalSince1970)".replacingOccurrences(of: ".", with: "") + ".db") 
      .absoluteString 

     var returnCode :Int32 = sqlite3_open(dbPath.cString(using: .utf8), &db) 
     if SQLITE_OK != returnCode { 
      preconditionFailure("Failed to open db") 
     } 

     var stmt :OpaquePointer? 
     returnCode = sqlite3_prepare_v2(db, "CREATE TABLE Things (name TEXT)".cString(using: .utf8), -1, &stmt, nil) 
     if SQLITE_OK != returnCode { 
      preconditionFailure("Failed to prepare table creation SQL") 
     } 

は、ここに私のコードです。私はC文字列に変換するときに文字列の異なるエンコーディングを使用しようとしました。具体的には、ASCIIエンコーディングを使用しようとしました。また、データベース名をハードコーディングしました。

sqlite3_prepare_v2でエラーが発生します。

エラーメッセージ\ \ U {01}「\そば」です「:構文エラー」

+1

使用 'sqlite3_errmsg()'エラーの理由を印刷します。 - Swift StringをC関数に直接渡すことができます。 'sqlite3_open(dbPath、&db)' –

+0

@MartinRエラーメッセージは "near \" \ u {01} \ ":syntax error" –

+0

です。http://stackoverflow.com/questions/34135305/nsfilemanager-defaultmanager-fileexistsatpathの重複-returns-false-trueの代わりに? - ファイルパスを得るのに 'absoluteString'を使わないでください。 –

答えて

1

私はC文字列の原因にスウィフト文字列を変換するために、100%を確認してくださいなぜあなた.cString(using: .utf8)アプローチ ないです問題。 Why does Swift return an unexpected pointer when converting an optional String into an UnsafePointer?(これは がSwiftバグとして報告されていました)と同じ問題になる可能性があります。明示的cString() の結果をアンラップすることを助けるようだ:

let sql = "CREATE TABLE Things (name TEXT)".cString(using: .utf8)! 
returnCode = sqlite3_prepare_v2(db, sql, -1, &stmt, nil) 

をしかし、あなたはconst char *String value to UnsafePointer<UInt8> function parameter behaviorを比較) を期待してC関数に直接スウィフトStringを渡すことができます。

var returnCode = sqlite3_open(dbPath, &db) 
// ... 
returnCode = sqlite3_prepare_v2(db, "CREATE TABLE Things (name TEXT)", -1, &stmt, nil) 

と予想されるので、これは動作します。

補足説明:ファイルパス文字列にURLを変換する

  • 使用.path、 ない.absoluteString
  • 何かが失敗した場合にエラーメッセージを表示するには、sqlite3_errmsg()を使用します。
  • var returnCode :Int32のように、不要な型名を削除します。

はすべて一緒にそれを置く:

var db: OpaquePointer? 
let dbPath = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) 
    .appendingPathComponent("xxx.db") 
    .path 

var returnCode = sqlite3_open(dbPath, &db) 
if SQLITE_OK != returnCode { 
    let errmsg = String(cString: sqlite3_errmsg(db)) 
    fatalError("Failed to open db: \(errmsg)") 
} 

var stmt: OpaquePointer? 
returnCode = sqlite3_prepare_v2(db, "CREATE TABLE Things (name TEXT)", -1, &stmt, nil) 
if SQLITE_OK != returnCode { 
    let errmsg = String(cString: sqlite3_errmsg(db)) 
    fatalError("Failed to prepare table creation SQL: \(errmsg)") 
}