El reino se bloquea con RLMException: el object se ha eliminado o se ha invalidado

Tengo un model de reino que almacena la línea de time (estoy haciendo la aplicación de edición de video) y con bastante frecuencia se aplasta al acceder a su propiedad RMArray. La aplicación ya está enviada y no la he experimentado yo mismo, pero mis críticos me avisan sobre este crash con bastante frecuencia. Aquí está el logging de locking:

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 

Aquí está el código 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 } } 

¿Alguien tiene una idea de lo que está mal con mi código?

Cuando el RLMProject se invalida, no será posible verificar la videoAssets.invalidated de videoAssets.invalidated o soundtracks.invalidated , por lo que su rastreo de stack muestra que se está RLMGetArray una exception no RLMGetArray en RLMGetArray .

Esto implica que el object se ha eliminado del reino antes de llamar a setTimeLineModel . Busque realm.deleteObject(_:) en su código para ver dónde podría estar sucediendo esto.

Finalmente, algunos consejos generales para hacer que su código sea un poco más seguro y simple:

En lugar de RLMRealm.defaultRealm() todas partes dentro de su RLMObject , debe usar su propiedad de realm . De esta manera, si decide cambiar la location de su reino en algún momento, su código dentro de su RLMObject seguirá funcionando.

Además, en lugar de crear una extensión en RLMArray para agregar un map, puede usar la function de map gratuito de Swift.

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