2017-08-14 11 views
4

他のスレッドで更新イベントを実行中にデータベースを削除しようとすると、Realmで一定のクラッシュが発生します。更新中に無効にするとRealmがクラッシュする

クラッシュがある:

2017-08-14 18:07:56.289 App Staging[28264:7828070] *** Terminating app due to uncaught exception 'RLMException', reason: 'Can only add, remove, or create objects in a Realm in a write transaction - call beginWriteTransaction on an RLMRealm instance first.' 
*** First throw call stack: 
(
    0 CoreFoundation      0x000000010c67fb0b __exceptionPreprocess + 171 
    1 libobjc.A.dylib      0x000000010c0e4141 objc_exception_throw + 48 
    2 Realm        0x0000000108095f96 _ZL27RLMVerifyInWriteTransactionP8RLMRealm + 86 
    3 Realm        0x000000010809710a RLMCreateObjectInRealmWithValue + 138 
    4 Realm        0x00000001080820af +[RLMObject createOrUpdateInRealm:withValue:] + 607 
    5 App Staging       0x0000000107497ae0 +[RealmRoundable createOrUpdateInRealm:withMemberResponse:] + 400 
    6 App Staging       0x0000000107497916 +[RealmRoundable createOrUpdateWithMemberResponse:] + 118 
    7 App Staging       0x000000010742a0a0 +[RealmStaff createOrUpdateInRealm:withResponse:inCareProvider:] + 352 
    8 App Staging       0x000000010742ab92 +[RealmStaff createOrUpdateInRealm:withStaff:inCareProvider:] + 514 
    9 App Staging       0x000000010742a94b +[RealmStaff createOrUpdateStaff:inCareProvider:] + 139 
    10 App Staging       0x000000010733b803 -[StaffRoundableTableViewController updateRoundables:fromDataLoader:inCareProvider:] + 131 
    11 App Staging       0x000000010747ae3a __54-[RoundableTableViewController dataLoaderDidLoadData:]_block_invoke.324 + 122 
    12 Realm        0x00000001081d01a6 -[RLMRealm transactionWithBlock:error:] + 86 
    13 Realm        0x00000001081d010e -[RLMRealm transactionWithBlock:] + 62 
    14 App Staging       0x000000010747ab0d __54-[RoundableTableViewController dataLoaderDidLoadData:]_block_invoke + 765 
    15 libdispatch.dylib     0x000000010e15c4a6 _dispatch_call_block_and_release + 12 
    16 libdispatch.dylib     0x000000010e18505c _dispatch_client_callout + 8 
    17 libdispatch.dylib     0x000000010e164dcd _dispatch_queue_override_invoke + 1321 
    18 libdispatch.dylib     0x000000010e166ec4 _dispatch_root_queue_drain + 634 
    19 libdispatch.dylib     0x000000010e166bef _dispatch_worker_thread3 + 123 
    20 libsystem_pthread.dylib    0x000000010e51c5a2 _pthread_wqthread + 1299 
    21 libsystem_pthread.dylib    0x000000010e51c07d start_wqthread + 13 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 

私が呼ぶときに発生:

として実装されている
[RealmManager deleteRealm]; 

:私の質問がある

+ (void)deleteRealm 
{ 
    @autoreleasepool { 
     [[RLMRealm defaultRealm] invalidate]; 
     // Hack to force Realm to clear cache because config is cached and crashes eventually because it detects encryption key has changed 
     SUPPRESS_UNDECLARED_SELECTOR_WARNING([[RLMRealm class] performSelector:@selector(resetRealmState)]); 
    } 

    NSFileManager *manager = [NSFileManager defaultManager]; 
    RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; 
    NSArray<NSURL *> *realmFileURLs = @[ 
             config.fileURL, 
             [config.fileURL URLByAppendingPathExtension:@"lock"], 
             [config.fileURL URLByAppendingPathExtension:@"log_a"], 
             [config.fileURL URLByAppendingPathExtension:@"log_b"], 
             [config.fileURL URLByAppendingPathExtension:@"note"], 
             [[config.fileURL URLByDeletingLastPathComponent] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.realm.management", [[config.fileURL URLByDeletingPathExtension] lastPathComponent]]] 
             ]; 
    for (NSURL *URL in realmFileURLs) { 
     NSError *error = nil; 
     [manager removeItemAtURL:URL error:&error]; 
     if (error) { 
      // handle error 
      DDLogError(@"Error deleting realm file - %@", error); 
     } 
    } 
} 

への道がありますこのコードを実行する前に、すべての領域操作を停止してください。レルムのドキュメントから

答えて

4

Deleting Realm Files上:

レルムは絶対に必要なときに、レルムによって管理されるすべてのオブジェクトは、ディスク上のファイルへの参照が含まれている以外のメモリへのデータのコピーを回避し、ファイルの前にすることができ、割り当て解除されなければならないので安全に削除してください。これには、レルムから読み込んだ(または追加した)すべてのオブジェクト、すべてRLMArrayRLMResults、およびRLMThreadSafeReferenceオブジェクト、およびRLMRealmオブジェクトが含まれます。

実際には、レルムファイルを削除するには、レルムを開く前にアプリケーションを起動するか、明示的な自動解放プール内でレルムを開いた後にレルムオブジェクトをすべて削除する必要があります割り当てが解除されました。

ファイルを別のスレッドでまだアクセスしている間に削除すると、さまざまな問題が発生します。レルムのプライベートメソッド(+[RLMRealm resetRealmState]など)を呼び出すこともできます。私は強くこれらのことをしないことを提案します。

これは、ディスクからRealmファイルを削除する動機付けに応じて、多少異なる方法でアプローチすることができます。ユースケースに関する情報をもっと分かち合うことができれば、より具体的な提案をすることができます。

たとえば、バックグラウンドスレッドがアクティブになっていて、アイドル状態になってから削除するかどうかを追跡できます。レルムへのすべての参照がファイルを削除する時点で削除されていることを確認するのに非常に注意する必要があります。そうしないと、すでに開いているファイルハンドルを介して削除されたファイルにアクセスし続ける可能性があります。

また、Realmファイルをただちに削除する代わりに、新しいRealmファイルの新しい一意のパスを生成することもできます。アプリケーションの残りの部分がそれらを使用していないことを確信しているときに、使用されていないレルムファイルを削除します(次の起動はこれを達成するための非常に信頼できる手段です)。そうでなければアプリライフサイクルのポイント古い状態にアクセスできないことがわかります)。これは、使用中にファイルを削除する機会がないので、私の好みになります。ユーザーごとの異なるレルムのパスは把握するのが比較的簡単な概念なので、ユーザーをログに記録するという概念を持つ多くのアプリケーションにも適しています。

+0

ユーザーがセッションを終了したときに、HIPAA準拠の理由で領域を削除します。私たちはEncrypted Core Dataでこの作業を行っていましたが、現在はRealmへのこの大きな移行を行い、データベースのすべてのトレースを削除するための監査に合格しています。 – ppaulojr

+0

暗号化されたレルムを使用し、セッションが終了したときに暗号化キーを破棄し、後でファイルをクリーンアップすると、要件を満たしますか? – bdash

+0

私はそれを販売しようとします。今はRealmファイルを削除する前にこれを実行してクラッシュすることを避けることができます。 – ppaulojr

関連する問題