我知道有很多关于这个主题的话题,但我觉得我的有点不同,因为我没有从数据库中保存或获取对象,它们一直在主线程上。
我的问题很奇怪,我可以在同一个类中修改 Realm 对象,但是当我将它作为参数传递给另一个对象时,就会出现类似的问题。我试图理解为什么会这样?它不应该发生。
'RLMException', reason: 'Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first.'
这是我的数据库结构:
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 } }
容器类:
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) }
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) }
对于获取对象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
对于这个例子,我们坚持使用空列表。进入正题。
将创建的事件(列表中只有一个元素/数量无关紧要)传递给:
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/