2017-10-29 20 views
0

このトピックに関するスレッドがたくさんあることは知っていますが、DBからオブジェクトを保存またはフェッチしていないため、メインスレッド上に常にあるので、 。書き込みトランザクション外のオブジェクトを変更する

私の問題はかなり厄介です。私は同じクラスのrealmオブジェクトを変更できますが、別のインスタンスに引数として渡すとそのようなものが発生します。私はなぜそれが起こっているのか理解しようとしていますか?それは起こるべきではありません。ここ

'RLMException', reason: 'Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first.' 

は私のデータベース構造である:

  1. 永続データベース内の各オブジェクトによって共有されるプロトコルです。

    public protocol Persistable { 
         associatedtype PropertyValue: PropertyValueType 
         associatedtype ManagedObject: RealmSwift.Object 
         associatedtype Query: QueryType 
    
         init(managedObject: ManagedObject) 
    
         func getManagedObject() -> ManagedObject 
        } 
    
        public typealias PropertyValuePair = (name: String, value: Any) 
    
        public protocol PropertyValueType { 
         var propertyValuePair: PropertyValuePair { get } 
        } 
    
        public protocol QueryType { 
         var predicate: NSPredicate? { get } 
         var sortDescriptors: [SortDescriptor] { get } 
        } 
    
  2. コンテナクラス:追加、更新、削除するためのイベントの全てを処理

    public final class Container { 
    let realm: Realm 
    
    public convenience init() throws { 
        try self.init(realm: Realm()) 
    } 
    
    internal init(realm: Realm) { 
        self.realm = realm 
    } 
    
    public func objects<T: Persistable>(_ type: T.Type) throws -> Results<T.ManagedObject> { 
        return realm.objects(type.ManagedObject.self) 
    } 
    
    public func write(_ block: (WriteTransaction) throws -> Void) throws { 
        let transaction = WriteTransaction(realm: realm) 
        try realm.write { 
         try block(transaction) 
        } 
    } 
    
    public func values<T> (_type: T.Type, maching query: T.Query) -> FetchResults<T> { 
        var results = realm.objects(T.ManagedObject.self) 
    
        if let predicate = query.predicate { 
         results = results.filter(predicate) 
        } 
    
        if !results.isEmpty { 
         results = results.sorted(by: query.sortDescriptors) 
        } 
    
        return FetchResults(results: results) 
    } 
    

    }

  3. WriteTransactionクラス(未実装)

    公衆finalクラスWriteTransaction { LETレルム:レルム

    internal init(realm: Realm) { 
        self.realm = realm 
    } 
    
    public func add<T: Persistable>(_ value: T, update: Bool) { 
        realm.add(value.getManagedObject(), update: update) 
    } 
    
    public func update<T: Persistable>(_ type: T.Type, values:[T.PropertyValue]) { 
        var dictionary: [String: Any] = [:] 
    
        values.forEach { 
         let pair = $0.propertyValuePair 
         dictionary[pair.name] = pair.value 
        } 
    
        realm.create(T.ManagedObject.self, value: dictionary, update: true) 
    } 
    
    public func delete<T: Persistable>(_ value: T) { 
        // TODO: Make it better. 
    

    //ガードせにObjC = realm.object(ofType:T.self、forPrimaryKey:value.getId())他{リターン} // realm.delete(にObjC) }}

  4. そしてフェッチがFetchResultsオブジェクトの場合:

    パブリック最終クラスFetchResults {

例のコードは次のようになります。私は、オブジェクトをフェッチ

ファーストクラス:

FirstClassの

ここでグローバル宣言です:

...イベント:オブジェクト{...}方法の一つで

var events: [Event]! 

、同じクラス - >の魅力として作品:

のは、このメソッドを介していくつかのオブジェクトをフェッチしてみましょう:(のDatabaseManagerがシングルトンである)

events = DataBaseManager.Instance.getObjects(Event.self, try! Container(), matching: .eventsFromPastDaysForOwner(username, Int(Date().timeIntervalSince1970) - 691200)) 

getObjects(...)

func getObjects<T, C>(_ type: T.Type, _ container: C, matching: T.Query) -> [T] where T : Persistable, C : Container { 
     var objects = [T]() 
     let fetchedObjects = container.values(_type: type, maching: matching) 
     for i in 0..<fetchedObjects.count { 
      objects.append(fetchedObjects.value(at: i)) 
     } 
     return objects 
    } 

オブジェクトがない場合l ETSはそれらを作成します。

if events.isEmpty { 
    events.append(Event(something: Something, something2: Something2)) 
} 

我々はイースリー、それらを変更することができます。

events[0].something = Something3 

この例では、我々は空のリストに固執します。ポイントに進む。

  1. パッシングがイベントを作成し(リスト内の唯一の要素を/それがどんなに多くのdoesntの):

    FUNCのgetEventsDurations(_イベント:[イベント]) - > [イベント]

我々はトンを変更する行を

events.first?.something = 0 

:イベントのいくつかの計算を持っているが、そこでクラッシュライン

彼は新しい価値を持っています。

どうしてですか?フェイルしたときにクラスの領域オブジェクトを変更すると、それは大丈夫でしたが、他のクラスではこのクラッシュがありましたか?

大変申し訳ありませんが、誰かがデータベースの構造を見たいと思っている場合に備えてです。

Btw。私は仕事をして、すべての変更を書き込みトランザクションの中に置くことができました:

try! container.write({ transaction in 

// Doing nothing, just modifying objects. 

    }) 

私はそれが醜いです。

ありがとうございます!

答えて

1

新しく作成されたオブジェクトは、保存する前にどこでも変更できます。しかし、オブジェクトからフェッチ/レルムに保存されている場合、レルムトランザクションを使用する必要があります。

+0

フェッチされたオブジェクトに対してレルムトランザクションを使用する必要があります。フェッチされた領域オブジェクトとデータベース内のオンの間には参照があるようです。それは効率的ですか? – yerpy

+0

効率的です。なぜデータベースが動作するのかを知りたいのであれば、私たちのウェブサイトにはたくさんのドキュメントがあります(この記事をチェックしてください:https://academy.realm.io/posts/jp-simard-realm-core-データベースエンジン/)。 – AustinZ

関連する問題