HOME > SwiftData+SqliteのDBファイル保存+Libraryフォルダから読込
前回の記事でSQLiteのラッパのRMDB, SWiftData,SQLite.swiftの検証の結果、SwiftDataを利用することにしました。 (前回の記事はこちらから)
さて、私の目標は事前に作成したSqliteのDBファイルをSwiftDataで読み込むことですので、その一連の作業を以下説明してまいります。
↓
↓
↓
↓
5. 完了
参考:IOS 8 Store sqlite File Location Core Data - Stack Overflow
参考:iOS - Xcode6のiPhone Simulatorのディレクトリが分かりにくかったけどいいアプリめっけた! - Qiita
参考:[iPhone] FMDB を使って SQLite データベースを設定する
参考:iOS開発に便利!SQLiteデータベースを手軽に編集できるツール「SQLite Database Browser」が大幅にバージョンアップしていた | Lancork
参考:今こそ復習したい、iOSアプリのディレクトリ構成 - Qiita
まず調査した中で、SQLite Database Browserというソフトウェアが便利そうなので利用してみます。前回の 記事ではFirefoxのSQlite managerを利用していましたが、やはり使用していないブラウザなのでこちらを利用してみます。 ダウンロードはこちらから。
記事のバージョンは3.2で大幅改善と記載されていますが、現状(2016/6月)では3.6まで開発が進んでいるようです
参考:iOS開発に便利!SQLiteデータベースを手軽に編集できるツール「SQLite Database Browser」が大幅にバージョンアップしていた | Lancork
参考:Macで「開発元が未確認の為開けません」と言われて開けないアプリを開く方法
試してみる、、、
えー、このSQLite Database Browserを今つかっているのですがかなり使い勝手が良いです。 直感的にDB+テーブル作成、情報のインサートがすんなりできました。FirefoxのSqlite managerより断然使い易い印象。 仕事でなれているphphmyadminよりもわかり易い第一印象です。
ただ、あれ、、、どうやってDBファイルに出力するんだろ、、、プロジェクトファイル、CSVやSQLへのエクスポートは すぐわかったんですが、肝心のDBファイルとしての出力に手間取っています。
→ (解決)ありました。というか、最初にNew Databaseした時に 作成したファイル自体がsqliteのDBファイルのようでした。拡張子が空白でしたのでわかっていませんでした。。。ここは *.sqliteみたいにしてて欲しかった。でも簡単に作成していた(簡単過ぎる)だけに灯台下暗しでした。これでファイル作成は完了です
Sqliteファイルの構成は以下の画像を参照下さい。サンプルのDBファイル自体をネット上で見つけられなかったので、 このsqliteファイルをアップロードしておきます。よろしければ自由にご利用ください!
BEGIN TRANSACTION;
CREATE TABLE "m_user" (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT
);
INSERT INTO `m_user` VALUES (1,'swift salaryman');
INSERT INTO `m_user` VALUES (2,'manga salaryman');
INSERT INTO `m_user` VALUES (3,'design salaryman');
COMMIT;
swiftsalaryman.sqlite(2k)をダウンロードはこちらをクリック
SwiftDataはデフォルトだと自動でDocumentフォルダにSwiftData.sqliteを作成してくれて便利なのですが、 今回私がやりたいのは「既に作成されてSQliteファイル」をLibraryフォルダから読み込むことです。 (Libraryフォルダに保存する理由は以下URLにも記載されていますが、Documentフォルダにはユーザが作成したデータを保存する 領域で《SwiftDataでユーザがデータテーブルを作成するのは問題無い》ですので、Libraryフォルダにsqliteを保存します。 開発者が事前に埋め込んだファイルがDocumentにあった場合リジェクトされる原因になるようです。) 参考:今こそ復習したい、iOSアプリのディレクトリ構成 - Qiita
まずDocumentとLibraryディレクトリを見てみましょう。
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String
println("Document Path:"+documentsPath)
let libraryPath = NSSearchPathForDirectoriesInDomains(.LibraryDirectory, .UserDomainMask, true)[0] as! String
println("Library Path:"+libraryPath)
ここで出力されたパスを、Finder → 移動 → フォルダに移動 から、該当場所にアクセスしてみましょう
するとSwiftDataを一度でも利用していればDocumentフォルダにSwiftData.sqliteが自動で作成されているのがわかります
今回はこのLibraryフォルダに上で作成したswiftsalaryman.sqliteをコピーします。
標準ではSwiftData.swiftはDocumentフォルダのSwiftData.sqliteにアクセスしますので、 SwiftData.sqliteの以下createPath関数を書き換えます。
class func createPath() -> String {
let docsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as! String
let databaseStr = "SwiftData.sqlite"
let dbPath = docsPath.stringByAppendingPathComponent(databaseStr)
return dbPath
}
↓
class func createPath() -> String {
let docsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.LibrarytDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as! String
let databaseStr = "swiftsalaryman.sqlite"
let dbPath = docsPath.stringByAppendingPathComponent(databaseStr)
return dbPath
}
これでswiftsalaryman.sqliteをオープンします
かなり簡単でした。上記のcreatePathさえ設定しておけば、 読み出すのは以下のexecuteQueryだけでOK。データベースをOpenする記述も必要なし(内部的に実行してくれている)
var result = NSMutableArray()
let (resultSet, err) = SD.executeQuery("SELECT * FROM m_user ORDER BY id DESC")
if err != nil {
//エラー処理
} else {
for row in resultSet {
if let id = row["id"]?.asInt() {
let nameStr = row["name"]?.asString()!
let dic = ["id":id, "name":nameStr!]
result.addObject(dic)
}
}
}
println(result.description);
以下、出力結果です。バッチリ取得できていました!
(
{
id = 3;
name = "design salaryman";
},
{
id = 2;
name = "manga salaryman";
},
{
id = 1;
name = "swift salaryman";
}
)
テーブルが存在するかを確認したり、テーブルを作成したり、Insert等のSQL処理も簡単にできますが、 今回の目標は達成できましたのでここで完了します。
さて上記のコードではエミュレータ上で試すには問題なかったのですが、端末でテストをすると以下エラーが
SwiftData Error -> During: SQL Prepare
-> Code: 1 - SQL error or missing database
-> Details: no such table: m_content
※m_contentは僕の自作のテーブル名ですのでこの箇所は可変です。
なんのエラーか調べると、どうやらLibraryフォルダにsqliteファイルが存在しない。。。。当たり前か、、、 プロジェクトに追加せずに直接Libraryフォルダに入れていたので納得です。ただ、LibraryフォルダにProjectから 直接配置することができませんので、XCodeのプロジェクトへドラッグで追加した上、Build PhaseでBundle(Copy Bundle Resourece)に含めた上で、 Libraryフォルダにsqliteファイルをコピーする処理を実装する必要があります。
処理の方法は以下で解説されていましたので共有します。
参考:How to use existing database #4
class func createPath() -> String {
let docsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.LibrarytDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as! String
let databaseStr = "swiftsalaryman.sqlite"
let dbPath = docsPath.stringByAppendingPathComponent(databaseStr)
return dbPath
}
↓
class func createPath() -> String {
let docsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.LibrarytDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as! String
let databaseStr = "swiftsalaryman.sqlite"
let dbPath = docsPath.stringByAppendingPathComponent(databaseStr)
// BEGING MODIFICATION
let fileMan = NSFileManager.defaultManager()
if !(fileMan.fileExistsAtPath(dbPath)) { // The database does not already exist in Documents directory
if let source = NSBundle.mainBundle().resourcePath?.stringByAppendingPathComponent(databaseStr) {
if !(fileMan.fileExistsAtPath(source)) {
println("SQLiteDB - file \(databaseStr) not found in bundle")
} else {
var error:NSError?
if !(fileMan.copyItemAtPath(source, toPath: dbPath, error: &error)) {
println("SQLiteDB - failed to copy writable version of DB!")
println("Error - \(error!.localizedDescription)")
}
}
}
}
// END MODIFICATION
return dbPath
}
指定の場所にファイルがなければBundleからコピーします。との内容です。すでに端末で試している人は空のSqliteファイルが SwiftDataによって作成されているかもしれませんので、一度端末のアプリを削除した上で実行してみてください。
これでSqliteをSwiftで使う目処がつきました。何かヘルプになっていれば幸いです。
2021-05-14 14:21:41 | WatchOSのwatchconnectivityのFiletransferの落とし穴。と、避け方。
AppleWatch 実機だと成功するんだけど、シュミレーターだと失敗するという、、、
昔作成してた時は成功してたのになーと思って調べると、どうやら昔は成功してたみたい。watchOS6以降は... |
2021-05-06 14:04:37 | LINEのアニメーションスタンプ制作の落とし穴、、、失敗談
ゴールデンウィークにLINEスタンプを作成してみました。
作り切って申請も通したんですが、意図したアニメーションと違う、、、、
LINEクリエーターの画面だと、アニメーションのプレビュー... |
2021-05-01 18:05:35 | 久しぶりのAdmobをobjective-cに実装。コンパイルエラーだらけ。バーミッション不具合でエミュレータにインスコできない。
忘れないようにメモ
エミュレータにアプリをインストールする際にパーミッション系のエラーがでた時、また、iphone実機にインストールする際にも権限系のエラーが出る場合。
ターゲット→ex... |
Tweet | |||
|