質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.45%

  • Swift 2

    1340questions

    Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

  • Realm

    264questions

    RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

  • iPad

    165questions

    iPadは、Appleがデザインしたタブレット型コンピュータです。iPadアプリケーションは通常Xcode IDEのObjective-Cで書かれますが、iPadアプリケーションを組むためのほかのツールを使うことも可能です。

CSVデータをRealmに編集可能で事前登録し、実機で実行するとエラーになる

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,175

Zan

score 16

以下のページを参考に、CSVデータをRealm用のDBファイルに変換後、アプリに登録して利用しています。

CSVデータをRealmに登録して最初からアプリに入れておく方法

当初はこのページと同様、読み取り専用にしていたのですが、その後書き込み可にしました。シミュレータでは正常に動いたのですが、実機(iPad)上で実行したところ、以下のエラーでアプリが終了してしまいました。

fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=2 "Operation not permitted" UserInfo={Error Code=2, NSFilePath=/var/containers/Bundle/Application/40A127E4-DA9E-4196-8376-7EDF196F9222/アプリ名.app/level0Dic.realm, NSLocalizedDescription=Operation not permitted}: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-703.0.18.8/src/swift/stdlib/public/core/ErrorType.swift, line 54

問題箇所のコードは以下になります。指定したファイルパスが良くないことは分かるのですが、具体的にどのように変更すべきなのでしょうか。

config = Realm.Configuration(
      path: NSBundle.mainBundle().pathForResource("level0Dic", ofType:"realm"), readOnly: false)

let realm = try! Realm(configuration: config)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

アプリケーションバンドル(NSBundle.mainBundle())にファイルを書き込むことはできません。バンドル内のファイルを変更することもできません。アプリケーションに含まれるファイルはすべて署名の対象なので、書きかわるとコード署名が意味をなさなくなるからです。
シミュレータで動作するのはシミュレータのアプリはコード署名はなく、サンドボックスの制限もないからです。(例えばシミュレータで実行中のアプリからデスクトップにあるファイルを読み書きできますが、デバイスでは当然できません)

なので、アプリケーションバンドル内のファイルを読み込むにはreadOnlytrueでなければなりません。初期データとしてバンドルに組み込んだファイルを使い、書き換えが必要な場合には書き込みのできるディレクトリにコピーしてから使用する必要があります。

例えば下記のようにします。

let filename = "level0Dic.realm"

let path = NSBundle.mainBundle().pathForResource(filename, ofType:nil)
let documentDirectory: NSString = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let realmPath = documentDirectory.stringByAppendingPathComponent(filename)

let fileManager = NSFileManager()
if !fileManager.fileExistsAtPath(realmPath) {
    try! fileManager.copyItemAtPath(path!, toPath: realmPath)
}

let config = Realm.Configuration(path: realmPath)
let realm = try! Realm(configuration: config)

また、Realmのバージョンがだいぶ古いようです。できれば最新バージョン、少なくとも1.0以上を使いましょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/11 12:40

    丁寧にご説明いただきありがとうございました。まずRealmを最新版にした後、教えていただいたようにコードを修正したところ、以下の箇所について、エラーが表示されました。
    「let config = Realm.Configuration(path: realmPath)」

    エラー: Cannot invoke value of type 'Realm.configuration.Type' with argument list '(path:String)'

    この箇所はどのように修正すればよろしいでしょうか。たびたび申し訳ありませんが、よろしくお願いします。

    キャンセル

  • 2016/09/11 13:07

    バージョン0.99から標準APIとの互換性を考慮して、`String`型の`path`を取るメソッドは無くなり、代わりに`NSURL`型の`fileURL`を取るメソッドに変わりました。(バージョンが古いことがわかったのも`path`を取るメソッドを使ってるからです)

    なので`Realm.Configuration()`の部分は例えば下記のように変更してください。

    ```swift
    let config = Realm.Configuration(fileURL: NSURL(fileURLWithPath: realmPath))
    ```

    キャンセル

  • 2016/09/11 14:29

    ありがとうございました。もう一点だけ質問させてください。教えていただいた以下のコード中のfileManagerの前についている「!」はどういう意味があるのでしょうか?

    if !fileManager.fileExistsAtPath(realmPath) {

    キャンセル

  • 2016/09/11 14:37

    否定の演算子です。すでにDocumentディレクトリにファイルがある場合にバンドルから再度コピーしてしまってはそれまでに編集した内容が失われてしまうので、まずコピー先にファイルがあるかどうかを確認し`fileManager.fileExistsAtPath(realmPath)`(ファイルがある場合は`true`が返るので無い場合という判定はそれの否定)、まだコピーされてない場合(≒1回目の起動時)のみコピーする、という処理になります。

    キャンセル

  • 2016/09/11 14:38

    ありがとうございます。大変勉強になりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.45%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Swift 2

    1340questions

    Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

  • Realm

    264questions

    RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

  • iPad

    165questions

    iPadは、Appleがデザインしたタブレット型コンピュータです。iPadアプリケーションは通常Xcode IDEのObjective-Cで書かれますが、iPadアプリケーションを組むためのほかのツールを使うことも可能です。