关于Realm数据库中的事务

时间:2017-06-05 05:19:43

标签: ios swift swift3 realm

这是我的Realm对象:

class AchievementDate : Object {

    dynamic var date: Date = Date()
    dynamic var apple: Int = Int(0)

    func save() {
        do {
            let realm = try Realm()
            try realm.write {
                realm.add(self)
            }
        } catch let error as NSError {
            fatalError(error.localizedDescription)
        }
    }
}

我在View控制器的viewDidLoad()方法中更改了apple的值,如您所见:

override func viewDidLoad() {      
    super.viewDidLoad()
    achievementDate.apple = 2
    achievementDate.save()    
}

然后当用户点击屏幕上的暂停按钮时,我会更新苹果的值,如下所示:

@IBAction func pausedButtonTapped(_ sender: UIButton) {
    achievementDate.apple += 1
    achievementDate.save()
}

Xcode成功运行它但当我点击暂停按钮时,应用程序崩溃了。在控制台中它说:

  

***由于未捕获的异常'RLMException'而终止应用程序,原因:'尝试修改写事务之外的对象 - 调用   首先在RLMRealm实例上使用beginWriteTransaction。'

我对此很困惑,顺便说一下,交易意味着什么?非常感谢。

2 个答案:

答案 0 :(得分:2)

写入事务用于将Realm中对象的修改分组到单个工作单元中。 Managed Realm对象只能在写入事务中进行修改。写入事务的范围限定为传递给Realm.write(_:)的调用的块。对write的调用开始写事务,在事务处于活动状态时执行正文,当块返回时,提交写事务并且更改将持久保存到Realm文件。

您尚未分享achievementDate的初始化方式,但根据您看到的AchievementDate实例是托管对象(即,它被创建然后添加到Realm,或者它是从Realm加载的)。如异常所述,您只能在写入事务中修改托管对象。您可以扩展写入事务的范围以包含对托管对象的修改,也可以避免完全修改托管对象(通过向模型类添加主键,并使用Realm.create(_:value:update:)或{{ 3}}使用update: true更新具有给定主键值的现有对象。)

答案 1 :(得分:1)

首先,如果要更新模型,则需要定义主键

class AchievementDate: Object {
    dynamic var id = 0
    dynamic var date:Date = Date()
    dynamic var apple:Int = Int(0)

    override static func primaryKey() -> String? {
        return "id"
    }
}

然后更新模型,如:

static func save(achievementDate:AchievementDate) {
    let realm = try! Realm()
    try! realm.write {
        realm.add(achievementDate, update: true)
    }
}

或者,如果您不想要主键,并且已经从Realm检索了模型,您可以像这样更新模型:

let realm = try! Realm()
try! realm.write {
    achievementDate.apple = 2
}