Realm,Object已被删除或失效

时间:2018-05-13 22:29:53

标签: ios swift realm rx-swift

我正在尝试构建一个新的iOS应用程序,并使用RxSwift Library和Realm作为数据库。

我构建了一个tableview,它显示了一个来自领域的对象列表,这些对象应该是可编辑的,可以删除。 (我没有使用tableview编辑功能。)

现在当我从表中删除一个项时,表应该刷新,因为我使用RxSwift将tableview绑定到Realm结果。但不是更新它崩溃了应用程序。

应用崩溃时遇到的错误是2018-05-14 00:09:34.660634+0200 RealmTest[65540:4239839] *** Terminating app due to uncaught exception 'RLMException', reason: 'Object has been deleted or invalidated.' *** First throw call stack: ( 0 CoreFoundation 0x000000010f76e1e6 __exceptionPreprocess + 294 1 libobjc.A.dylib 0x000000010ee03031 objc_exception_throw + 48 2 Realm 0x000000010d44abd3 _ZL17RLMVerifyAttachedP13RLMObjectBase + 83 3 Realm 0x000000010d44c89c _ZN12_GLOBAL__N_18getBoxedIN5realm10StringDataEEEP11objc_objectP13RLMObjectBasem + 28 4 Realm 0x000000010d44c877 ___ZN12_GLOBAL__N_115makeBoxedGetterIN5realm10StringDataEEEP11objc_objectm_block_invoke + 39 5 RealmTest 0x000000010cf9c6a9 _T09RealmTest0B9ModelItemV8identitySSvg + 41 6 RealmTest 0x000000010cf9c6f5 _T09RealmTest0B9ModelItemV14Differentiator16IdentifiableTypeAadEP8identity8IdentityQzvgTW + 21 7 Differentiator 0x000000010d29f24e _T014Differentiator4DiffO23calculateAssociatedData33_D199D3FBF4B7CA3AFA95223EE09B4772LLs15ContiguousArrayVyAGyAC04ItemdE0AELLVGG_AKtAGyAGyxGG07initialP5Cache_AM05finalpR0tKAA16IdentifiableTypeRzlFZ + 2094 8 Differentiator 0x000000010d2ac30e _T014Differentiator4DiffO16CommandGenerator33_D199D3FBF4B7CA3AFA95223EE09B4772LLV22calculateItemMovementss15ContiguousArrayVyAIyAC0N14AssociatedDataAELLVGG_AMtAIyAIy0N0QzGG07initialN5Cache_AQ05finalnU0AIyAC07SectionrS0AELLVG0twS0AV0vwS0tKFZ + 334 9 Differentiator 0x000000010d2a1d65 _T014Differentiator4DiffO16CommandGenerator33_D199D3FBF4B7CA3AFA95223EE09B4772LLV27generatorForInitialSectionsAFy_xGSayxG_AI05finalP0tKFZ + 1253 10 Differentiator 0x000000010d2a1395 _T014Differentiator4DiffO27differencesForSectionedViewSayAA9ChangesetVyxGGSayxG15initialSections_AI05finalI0tKAA26AnimatableSectionModelTypeRzlFZ + 277 11 RxDataSources 0x000000010e35ede4 _T013RxDataSources0a26TableViewSectionedAnimatedB6SourceC05tableE0ySo07UITableE0C_0A5Swift5EventOySayxGG08observedL0tFyACyxG_AJtcfU_yycfU_ + 660 12 RxDataSources 0x000000010e360049 _T013RxDataSources0a26TableViewSectionedAnimatedB6SourceC05tableE0ySo07UITableE0C_0A5Swift5EventOySayxGG08observedL0tFyACyxG_AJtcfU_yycfU_TA + 25 13 RxDataSources 0x000000010e35f63d _T0Ieg_IeyB_TR + 45 14 libdispatch.dylib 0x0000000113b5b807 _dispatch_call_block_and_release + 12 15 libdispatch.dylib 0x0000000113b5c848 _dispatch_client_callout + 8 16 libdispatch.dylib 0x0000000113b6792b _dispatch_main_queue_callback_4CF + 628 17 CoreFoundation 0x000000010f730c99 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 18 CoreFoundation 0x000000010f6f4ea6 __CFRunLoopRun + 2342 19 CoreFoundation 0x000000010f6f430b CFRunLoopRunSpecific + 635 20 GraphicsServices 0x0000000117bb5a73 GSEventRunModal + 62 21 UIKit 0x000000010fbeb0b7 UIApplicationMain + 159 22 RealmTest 0x000000010cf9a0a7 main + 55 23 libdyld.dylib 0x0000000113bd9955 start + 1 24 ??? 0x0000000000000001 0x0 + 1 ) 此外,我在输出中得到了堆栈跟踪,但我找不到崩溃发生的原因/来源。

输出堆栈跟踪:

{{1}}

我的问题是,如果有人知道我做错了什么,并且使用RxSwift和Databinding来删除领域对象的正确方法是什么?

编辑:

我制作了一个小型测试项目并将其放在我的github上,当你选中deleteFirst按钮时会出错。 https://github.com/Hiiragisan09/ios-example-project-realm-test

Screenshot of the app crash

2 个答案:

答案 0 :(得分:2)

我找到了解决方案。

当我开始使用Realm时,我不知道如果删除它,该对象会发生变异。

这是一个有点困难,因为当领域崩溃时,领域对象已被删除或无效'它没有给出你试图访问realmobject属性的堆栈跟踪。

因此,当您从Realm中删除项目时,它将触发表格以获取新项目,并且因为该表格是动画的,所以它将尝试使用旧数据来区分新数据。当Diff尝试访问旧数据中的属性时,它将崩溃。

要解决此问题,我创建了表示表中数据的结构。因此,当我删除Realm对象时,表格不会崩溃,因为Diff仍然可以访问旧数据。

我在Realm How to save a struct to realm in swift

中使用结构的方式

答案 1 :(得分:0)

我遇到了同样的问题。然后我读了马丁的回答。我给了他赞成票,因为对问题进行分类对我来说是最难的部分。但我实施了与他不同的解决方案。鉴于问题的范围,在我的 Realm 数据模型之上添加一个基于结构的存储库层感觉很沉重。

我的轻量级解决方案: 我在我的 collectionView 重载方法中添加了一个参数来控制重载动画。我默认参数为true,然后覆盖它并根据需要将其设置为false。 collectionView 不会尝试访问旧的/已删除的 Realm 对象,因为它不会尝试为视图中的旧元素设置动画。问题解决了。

func displayRecipes(_ recipes: [Recipe], withAnimations: Bool = true) {
...
      dataSource?.apply(snapshot, animatingDifferences: withAnimations)
}