2016-11-22 9 views
1

私はMVVMを使用しようとしていますRealm 2.0.4とReactiveCococa 2.5(Objective-CのAPI)レルムと反応ココア

を使用しています。

VMを基になるRLMObjectに「バインド」しようとしています。私はいくつかの成功を収めました。このような。

RACSignal *invalidationSignal = [[[RACObserve(self, boundedProfile.invalidated) 
            takeUntil:self.rac_willDeallocSignal] 
            filter:^BOOL (NSNumber *invalid) { 
             return [invalid boolValue] == true; // We're only interested in the cases where it was invalidated. 
            }] 
           replayLast]; // For multicasting the same value for all subscribers. 
@weakify(self); 
self.updateSignalDisposable = [[RACObserve(self, boundedProfile.currentProfileTimestamp) 
           takeUntil:invalidationSignal] 
           subscribeNext:^(id x) { 
            @strongify(self) 
            CYRLMProfile * profile = [CYRLMProfile profileWithID:self.userId]; 
            self.userId    = profile.userId; 
            ... 
           }]; 

ここに私の問題は私のVMがdealloc'edますとき、私は私のレルムオブジェクトにnilを設定し、それはまた、有界オブジェクトに関連付けられたrealmの割り当てを解除することです。

これは、Realmが書き込みトランザクションの途中にあるときに発生します。実行中のスレッドの別のスレッドで書き込みトランザクションをキャンセルしているためクラッシュします。

EDIT:

が問題に展開するには: - RealmObjectは、任意のスレッド からレルムから取得されたことを - - ViewModelに割り当てが解除されたとき、私はRealmObject への強い参照してViewModelにを持っています: - RealmObjectは、そのオブジェクトへの唯一の強力な参照であったため、解放されてしまいました - そのオブジェクトのRLMRealmは、その領域への残りの強力な参照であるため解放されます。 - それが書き込みトランザクション中で、そうであればキャンセルして間違ったスレッドでクラッシュする

RAC観測を削除しても、問題はまだ発生します。 main以外のスレッドにrealmオブジェクトを持つビューモデルを作成してbeginWriteTranscactionを呼び出し、そのオブジェクトをメインスレッドでアンロードして割り当てを解除することで、これを強制的に再現することができます コードは

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 

    RLMRealm *realm = [RLMRealm defaultRealm]; 
    CYRLMProfile *profile = [CYRLMProfile profileWithId:10 inRealm:realm]; 
    __block ViewModel *vm = [ViewModel viewModelWithProfile:profile]; 

    [realm beginWriteTransaction]; 

    dispatch_async(dispatch_get_main_queue(), ^{ 

     vm = nil; 
    }); 
}); 
+0

また、取得したエラーメッセージやスタックトレースなどを共有できますか?また、アプリ内の各スレッドのRealmの新しいインスタンスを初期化する必要があります。詳しくは、スレッド:https://realm.io/docsのスレッドを参照してください。/objc/latest /#threading – Dmitry

+0

メッセージは "不正なスレッドからアクセスされた領域"で、ここにstacktraceがあります:http://pastebin.com/s0GKVjwq –

答えて

0

Realm accessed from incorrect threadは、別のスレッドで作成されたレルムインスタンスにアクセスしようとしたことを意味します。上記のコメントで提案したように、各スレッドのRealmの新しいインスタンスを初期化し、そのRealmインスタンスからオブジェクトの新しいインスタンスを取得してください。

あなたが知っておく必要はあり唯一のことは、あなたがレルムオブジェクトの同じインスタンスを共有する複数のスレッドを持つことができないということです。複数のスレッドが同じオブジェクトにアクセスする必要がある場合は、それぞれ独自のインスタンスを取得する必要があります。

詳細はhttps://realm.io/docs/objc/latest/#threadingを参照してください。

+0

ここでの問題は、スレッド内のオブジェクトをバインドすることですオブジェクトがバインドされていたスレッドに関する警告ではありませんでした)。しかし、すべてのdeallocがメインスレッドで発生しました。私は、オブジェクト自体にアクセスしようとせず、割り当てを解除するだけです。 Realmオブジェクトのdeallocは、作成された同じスレッド上で発生する必要がありますか? –

+0

「RACObserve」(KVO)の場合、イベントは変更が加えられた同じスレッドで配信されます。メインスレッドで 'RACObserver'を呼び出しますか? – Dmitry

+0

私は 'RACObserve'をメインスレッドで強制的に呼び出すつもりはありませんでした。しかし、私はそれを行うことができます。しかし、私はdealloc'ingときに一貫性のないスレッドを防ぐために、メインスレッドで呼び出される必要があることがわかります。それは何をすべきか?正直なところ、私のアプローチが「正しい」場合、またはこれを達成するためのより良い方法がある場合は、いくつかの検証がほしいと思っていました。 –

関連する問題