领域与RLMException崩溃:对象已被删除或无效

我有一个存储时间线的领域模型(我正在制作video编辑应用程序),而且经常碰到访问它的RMArray属性。 该应用程序已经发货,我没有经历过自己,但我crushlytics通知我经常这样的崩溃。 这是崩溃日志:

Fatal Exception: RLMException Object has been deleted or invalidated. Thread : Fatal Exception: RLMException 0 CoreFoundation 0x2614d45f __exceptionPreprocess + 126 1 libobjc.A.dylib 0x3407ec8b objc_exception_throw + 38 2 VideoEditor 0x00293919 RLMGetArray(RLMObjectBase*, unsigned int, NSString*) (RLMRealm_Private.hpp:38) 3 VideoEditor 0x0018a1b4 VideoEditor.RLMProject.setTimeLineModel (VideoEditor.RLMProject)(VideoEditor.TimeLineModel, beginWriteTransaction : Swift.Bool) -> () (RealmModels.swift:147) 4 VideoEditor 0x0025eb9c VideoEditor.VideoEditorAPI.saveProject (VideoEditor.VideoEditorAPI)(Swift.Optional<VideoEditor.IProject>, timeLine : VideoEditor.TimeLineModel, name : Swift.String, filterID : Swift.Int, image : ObjectiveC.UIImage) -> Swift.ImplicitlyUnwrappedOptional<VideoEditor.IProject> (VideoEditorAPI.swift:42) 5 VideoEditor 0x00164754 @objc VideoEditor.ProjectEditorViewController.saveProject (VideoEditor.ProjectEditorViewController)(Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSNotification>) -> () (ProjectEditorViewController.swift:514) 6 CoreFoundation 0x26105e31 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12 7 CoreFoundation 0x260616cd _CFXNotificationPost + 1784 8 Foundation 0x26db7dd9 -[NSNotificationCenter postNotificationName:object:userInfo:] + 72 9 UIKit 0x296cae2d -[UIApplication _deactivateForReason:notify:] + 528 10 UIKit 0x298d2dd7 -[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:] + 1846 11 UIKit 0x298caafd -[UIApplication workspace:didReceiveActions:] + 80 12 FrontBoardServices 0x2ca180a9 __31-[FBSSerialQueue performAsync:]_block_invoke + 12 13 CoreFoundation 0x26113fe5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12 14 CoreFoundation 0x261132a9 __CFRunLoopDoBlocks + 216 15 CoreFoundation 0x26111de3 __CFRunLoopRun + 1714 16 CoreFoundation 0x2605f3b1 CFRunLoopRunSpecific + 476 17 CoreFoundation 0x2605f1c3 CFRunLoopRunInMode + 106 18 GraphicsServices 0x2d5bf201 GSEventRunModal + 136 19 UIKit 0x296c943d UIApplicationMain + 1440 20 MerryVideoEditor 0x0028c88f main (main.m:16) 21 libdyld.dylib 0x3460aaaf start + 2 

这里是RLMProject代码:

 protocol IProject{ var name: String { get set } var filterID: Int { get set } var filterIntensity: CGFloat { get set } /// duration in seconds var duration: Int { get set } var dateCreated: NSDate { get } func setTimeLineModel(timeLine: TimeLineModel, beginWriteTransaction: Bool) // should be done by ProjectImporter func getTimeLineModel() -> TimeLineModel var videoAssets: RLMArray { get } var soundtracks: RLMArray { get } } class RLMProject: RLMObject, IProject, Printable { dynamic var videoAssets: RLMArray = RLMArray(objectClassName: RLMMediaAsset.className()) dynamic var soundtracks: RLMArray = RLMArray(objectClassName: RLMMediaAsset.className()) dynamic var name: String = "" dynamic var filterID: Int = 0 dynamic var filterIntensity: CGFloat = 1 dynamic var duration: Int = 0 dynamic var dateCreated: NSDate = NSDate() dynamic var idValue: Int = 0 func setTimeLineModel(timeLine: TimeLineModel, beginWriteTransaction: Bool = true) { func updateArray(array: RLMArray, withAssetsArray assetsArray: [MediaAsset], type: MediaType){ array.removeAllObjects() for asset in assetsArray{ let model = RLMMediaAsset() model.setMediaAsset(asset) model.setType(type) array.addObject(model) RLMRealm.defaultRealm().addObject(model) } } if beginWriteTransaction { RLMRealm.defaultRealm().beginWriteTransaction() } if videoAssets.invalidated { videoAssets = RLMArray(objectClassName: RLMMediaAsset.className()) } if soundtracks.invalidated { soundtracks = RLMArray(objectClassName: RLMMediaAsset.className()) } updateArray(videoAssets, withAssetsArray: timeLine.videoAssets, .Video) updateArray(soundtracks, withAssetsArray: timeLine.soundtracks, .Soundtrack) duration = Int(CMTimeGetSeconds(timeLine.totalDuration)) dateCreated = NSDate() if beginWriteTransaction { RLMRealm.defaultRealm().commitWriteTransaction() } } func getTimeLineModel() -> TimeLineModel { let timeLine = TimeLineModel() timeLine.videoAssets = videoAssets.map { ($0 as RLMMediaAsset).getMediaAsset() } timeLine.soundtracks = soundtracks.map { ($0 as RLMMediaAsset).getMediaAsset() } return timeLine } } extension RLMArray { func map<U>(transform: (RLMObject) -> U) -> [U]{ var array: [U] = [] for object in self{ array.append(transform(object)) } return array } } 

有人知道我的代码有什么问题吗?

RLMProject本身失效时,将无法检查videoAssets.invalidatedsoundtracks.invalidated ,这就是为什么你的堆栈跟踪显示在RLMGetArray中抛出一个未被捕获的exception。

这意味着在调用setTimeLineModel之前,对象已经从领域中删除了。 请在您的代码中查找realm.deleteObject(_:) ,以查看可能发生的情况。

最后,提供一些使您的代码更安全和简单的一般技巧:

在你的RLMObject每个地方,不要使用RLMRealm.defaultRealm() ,你应该使用它的realm属性。 这样,如果你决定改变你的领域的位置,你的RLMObject的代码将继续工作。

而且,不是在RLMArray上添加扩展来添加地图,而是使用Swift的免费mapfunction。

 map(videoAssets) { ($0 as RLMMediaAsset).getMediaAsset() }