修改写事务之外的对象

时间:2017-10-29 10:17:07

标签: swift realm

我知道关于这个主题有很多线索,但我认为我有点不同,因为我没有保存或从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 类处理添加,更新,删除(尚未实现)的所有事件

    public final class WriteTransaction {     让境界:境界

    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.
    

    // guard let objc = realm.object(ofType:T.self,forPrimaryKey:value.getId())else {return} // realm.delete(objc)     } }

  4. 对于提取对象 FetchResults

    公共最终类FetchResults {

        internal let results: Results<T.ManagedObject>
    
        public var count: Int {
            return results.count
        }
    
        internal init(results: Results<T.ManagedObject>) {
            self.results = results
        }
    
        public func value(at index: Int) -> T {
            return T(managedObject: results[index])
        }
    }
    
  5. 示例代码为:

    我获取对象的第一课:

    FirstClass

    这是一份全球声明:

    ...事件:对象{...}

    var events: [Event]!
    

    在其中一种方法中,同一类 - &gt;充当魅力:

    让我们通过这个方法获取一些对象:( 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
        }
    

    如果没有对象,我们可以创建它们:

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

    我们可以轻松修改它们:

    events[0].something = Something3
    

    对于这个例子,我们坚持使用空列表。向前迈进。

    1. 将创建的事件(列表中只有一个元素/无关紧要)传递给:

      func getEventsDurations(_ events:[Event]) - &gt; [事件]

    2. 对事件有一些计算,但崩溃的行就在那里:

      events.first?.something = 0
      

      我们用新值修改对象的行。

      为什么会这样?当我修改类中的领域对象时,我确实获取它没关系,但在其他类中得到了这个崩溃?

      我很抱歉有很多代码,但是如果有人想看一下数据库结构的话,就是这样。

      顺便说一下。我可以解决并在写入事务中放置每个修改:

      try! container.write({ transaction in
      
      // Doing nothing, just modifying objects.
      
          })
      

      来吧,这太丑了。

      提前致谢!

1 个答案:

答案 0 :(得分:4)

您可以在保存之前在任何位置修改新创建的对象。但是,如果它是从某个领域获取/保存到领域的对象,则必须使用领域事务。