22

アプリ ストアにアプリがあり、ロギング サービスを使用してクラッシュ ログと関連するログ データを取得しています。断続的なクラッシュ (影響を受けるユーザーの数が少なく、ユーザーごとのクラッシュの数が少ない) が見られますが、困惑しています。

これらのクラッシュで何が起こるかは次のとおりです。

  1. アプリが Core Data スタックを起動して初期化する

  2. アプリは、次のコードを使用して NSPersistentStoreCoordinator に SQL ストアを追加しようとします (storeURL有効です)。

    NSDictionary *options = @{
        NSMigratePersistentStoresAutomaticallyOption : @(YES),
        NSInferMappingModelAutomaticallyOption : @(YES)
    };
    
    sqlStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                         configuration:nil
                                                                   URL:storeURL
                                                               options:options
                                                             error:&error];
    
  3. このストアを追加するときに、次のいずれかのエラーが発生します:

NS エラー:

Domain=NSCocoaErrorDomain
Code=256 "The operation could not be completed. (Cocoa error 256.)"
UserInfo=0x1dd946a0 {NSUnderlyingException=authorization denied, NSSQLiteErrorDomain=23}

また

NS エラー:

Domain=NSCocoaErrorDomain
Code=256 "The operation could not be completed. (Cocoa error 256.)"
UserInfo=0xc6525d0 {NSUnderlyingException=disk I/O error, NSSQLiteErrorDomain=10}

この状態の後、アプリが機能するには SQL ストアが必要なため、アプリがクラッシュします。新しい storeURL を試すことで、この失敗を適切に処理しようとすることもできますが、ユーザーが既存のデータを失うことは望ましくありません。また、私はこの問題を個人的に再現したことはありません。影響を受けるユーザー数が少なく、クラッシュ ログに基づいて、影響が少ない問題であり、その後のアプリの起動時に再発することはないと考えています。

これらの状態をデバッグおよび防止/処理する方法についていくつかの提案をしてくれる Core Data の第一人者がそこにいることを願っています。私のコア データ スタック初期化コードは xcode プロジェクト ジェネレーターから直接作成されたものであり、永続ストア コーディネーターが (起動時に) 1 回だけ初期化され、この初期化でこのエラーが発生するという点で、同時実行の問題を除外しました。

関連する場合は、より多くのコード/情報を提供してください。

ありがとう!

4

4 に答える 4

30

XJones のようで、原因を突き止めることができました。これは、iOS のエッジケースのバグか、文書化されていない動作のようです。私はこれを Apple バグ ID 12935031 として提出しました。

iOS 5 の時点で Core Data ストアがデフォルト。

再現する手順:

1) デバイスでパスコード保護を有効にする

2) 重要位置監視または地域監視を開始し、バックグラウンドでも開始し続けるアプリケーションを作成します。すなわち。バックグラウンドでの重要な場所の変更または地域の監視を使用するアプリ。

3) デバイスのバッテリーがなくなるまで待ちます (他の原因も考えられます)。

4) デバイスがシャットダウンします

5) デバイスを Mac に接続する

6) 充電が十分になると、デバイスが起動します。重要: この時点ではデバイスのロックを解除しないでください。

7) 監視範囲を出入りする、または場所に重大な変化が生じる原因となる。重要な場所の監視または地域の監視に登録されているため、デバイスはアプリケーションを自動的に再起動します

8) ただし、デバイスはユーザーによってロック解除されていないため (パス コードがまだ入力されていない)、アプリケーションは保護されたデータ ファイルを読み取ることができません。Core Data アプリケーションでは、これにより、永続ストア コーディネーターが永続ストア ファイルを管理対象オブジェクト コンテキストに追加できなくなります。これにより、アプリがクラッシュするか、開発者が使用するコードによってはデータベースのリセットが試行されることさえあります。他のアプリでは、他の理由でクラッシュが発生する可能性があります。これは、iOS 5 以降の Core Data ストアでデフォルトで有効になっているデータ保護機能の予想外の文書化されていない副作用であるためです。

Apple がこれを修正するか少なくとも文書化するまでの解決策または回避策は、アプリケーションが applicationWillTerminate での重要な場所の変更/リージョンの監視を停止することを確認するか、オプション辞書の NSFileProtectionKey キーに NSFileProtectionNone を設定してデフォルトのデータ保護機能をオフにすることです。 Core Data ストアを永続ストア コーディネーターに追加します。保護されたデータが利用可能になるかどうかを確認する while() ループを使用して、ファイル ストアが利用可能になるのを待ちます。KVO を使用してこれを行う方法は他にもあるかもしれませんが、この方法は確実に機能し、アプリケーションの起動プロセス全体をやり直すことなく既存のコードに挿入するのが最も簡単です。

更新: ストアでデータ保護が既に有効になっている場合、そのキーを設定するだけでは十分ではないようです。手動で設定する必要があります:

[[NSFileManager defaultManager] setAttributes:[NSDictionary dictionaryWithObject:NSFileProtectionNone forKey:NSFileProtectionKey] ofItemAtPath:storePath error:nil];

XJones からのより多くのインプットと、Apple の散在するドキュメントでのもう少しの調査のおかげで、バックグラウンドでの位置監視が必要なアプリの修正は次のとおりです。

while(![[UIApplication sharedApplication] isProtectedDataAvailable]) {
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5f]];
}

このコードは、ストア データ ファイルを永続ストア コーディネーターに追加する前に実行されます。

2015 年更新: NSPersistentStoreFileProtectionKey を NSFileProtectionNone に設定することもできます。これにより、ファイル保護が適切に無効になり (不要な場合)、回避策を必要とせずに機能します。以前の試みでうまくいかなかった理由は、私がテストしていた辞書のキーが間違っていたからです。

于 2012-12-27T07:15:59.677 に答える
4

UIApplicationドキュメントで次の通知に気付きました。

UIApplicationProtectedDataDidBecomeAvailable UIApplicationProtectedDataWillBecomeUnavailable

これらは iOS 4.0 以降で使用できます。@lupinglade、これらの通知を観察し、保護されたファイル(ストアなど)にのみアクセスする必要があると思いますUIApplicationProtectedDataDidBecomeAvailable.

于 2013-01-29T01:50:08.033 に答える
3

@lupinglade のソリューションは、私の場合はほとんど機能しました (再起動からの起動時に VoIP アプリが機能していました) が、保護されたデータが利用可能になったときに呼び出される AppDelegate のデリゲート関数があることも指摘したいと思います。

applicationProtectedDataDidBecomeAvailable:

これにより、私の場合、ソリューションの実装が少し簡単になりました。

ヘッダー ファイルによると、iOS 4 以降で使用できます。

于 2013-10-15T12:27:29.800 に答える
0

ここでも同じ問題がありますが、まだ解決策を見つけることができていません。デバイスにロックコードが設定されていることに関連しているようです。ロックコードがないと、エラーを再現することはできませんでしたが、今では何度も再現することができました。コンソールログは次のとおりです。

エラーは次のとおりです。ErrorDomain=NSCocoaErrorDomain Code = 256 "操作を完了できませんでした。(Cocoaエラー256)" UserInfo = 0x1fd80110 {NSUnderlyingException =認証が拒否されました、NSSQLiteErrorDomain = 23}

ファイルは存在し、暗号化を使用していません。

于 2012-12-23T20:12:33.150 に答える