swift - 在写入事务之外修改对象

标签 swift realm

我知道有很多关于这个主题的话题,但我觉得我的有点不同,因为我没有从数据库中保存或获取对象,它们一直在主线程上。

我的问题很奇怪,我可以在同一个类中修改 Realm 对象,但是当我将它作为参数传递给另一个对象时,就会出现类似的问题。我试图理解为什么会这样?它不应该发生。

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

这是我的数据库结构:

  1. Persistable 是数据库中每个对象共享的协议(protocol)。

        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)最终类 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:

    公共(public)最终类 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])
        }
    }
    

示例代码为:

我获取对象的第一个类:

头等舱

这是一个全局声明:

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

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
    }

如果没有对象让我们创建它们:

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

我们可以很容易地修改它们:

events[0].something = Something3

对于这个例子,我们坚持使用空列表。进入正题。

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

    func getEventsDurations(_ events: [Event]) -> [Event]

它对事件进行了一些计算,但崩溃的行是:

events.first?.something = 0

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

为什么会这样?当我在获取时修改类上的 Realm 对象时,它没问题,但在其他类中发生了崩溃?

我很抱歉有很多代码,但这只是为了以防万一有人想看看数据库结构。

顺便说一句。我可以变通并将所有修改放入写入事务中:

try! container.write({ transaction in

// Doing nothing, just modifying objects.

    })

拜托,那太丑了。

提前致谢!

最佳答案

您可以在保存之前在任何地方修改新创建的对象。但是,如果它是从 Realm 获取/保存到 Realm 的对象,那么您必须使用 Realm 事务。

关于swift - 在写入事务之外修改对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46999023/

相关文章:

ios - 使用 Alamofire 和 realm.io 进行分页

android - 将封装在RealmList中的嵌套Realm对象查询到RealmResults中

ios - 如何在 TableViewController 中设置多个 segue ViewController?

swift - SceneKit 弹性地板

ios - 辅助功能 VoiceOver 不适用于 UILabel

swift - 使用 Decodable 的 Realm 快速列表

Swift 深 NSObjects 不编译

ios - 防止 TableView 单元格在单元格操作后关闭

ios - 使用 Realm 为新属性赋值时发生崩溃

java - 如何在Realm中保存相关类?