领域崩溃与RLMException:对象已被删除或无效 [英] Realm crashes with RLMException: object has been deleted or invalidated
问题描述
致命异常:RLMException
对象已被删除或无效。
线程:致命异常: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基础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代码:
协议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)
//应该由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
动态var dateCreated:NSDate = NSDate()
动态变量idValue:Int = 0
func setTimeLineModel(timeLine:TimeLineModel,beginWriteTransaction:Bool = true){
func updateArray(array:RLMArray,withAssetsArray assetsArray:[MediaAsset],type:MediaType){
array.removeAllObjects()
为assetsArray {
let model = RLMMediaAsset()
型号.setMediaAsset(asset)
model.setType(type)
array.addObject(model)
RLMRealm.defaultRealm()。addObject(model)
}
}
如果beginWriteTransaction {RLMRealm.defaultRealm()。beginWriteTransaction()}
如果videoAssets.invalidated {videoAssets = RLMArray(objectClassName:RLMMediaAsset.className())}
如果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()
如果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
}
}
扩展名RLMArray {
func map< U>(transform: RLMObject)→U)→> [U] {
var array:[U] = []
对于self中的对象{
array.append(transform(object))
}
返回数组
}
}
有人知道我的代码有什么问题?
当 RLMProject
本身无效时,可以检查 videoAssets.invalidated
或 soundtracks.invalidated
,这就是为什么你的堆栈跟踪显示一个未捕获的异常被引入 RLMGetArray
。
这意味着该对象在您调用 setTimeLineModel
。请在您的代码中查找 realm.deleteObject(_:)
以查看可能发生的情况。
最后,一些一般的提示,使您的代码更安全和更简单:
而不是 RLMRealm.defaultRealm()
您的 RLMObject
内的任何地方,您应该使用其领域
属性。这样,如果您决定在某个时候更改您的领域位置,您的 RLMObject
中的代码将继续运行。
另外,而不是在 RLMArray
上创建扩展名来添加地图,您可以使用Swift的免费地图
功能。
map(videoAssets){($ 0 as RLMMediaAsset).getMediaAsset()}
I have a realm model that stores time line (i am making video editing app) and quite frequently it crushes on accessing it's RMArray property. The app is already shipped and I haven't experienced it myself but my crushlytics notifies me about this crash quite oftenly. Here is the crash log:
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
Here is the RLMProject code:
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
}
}
Does anybody has an idea what is wrong with my code?
When the RLMProject
itself is invalidated, it won't be possible to check for videoAssets.invalidated
or soundtracks.invalidated
, which is why your stack trace shows that an uncaught exception is being thrown in RLMGetArray
.
This implies that the object has been deleted from the realm before you call setTimeLineModel
. Please look for realm.deleteObject(_:)
in your code to see where this might be happening.
Finally, a few general tips to make your code a little safer and simpler:
Instead of RLMRealm.defaultRealm()
everywhere inside your RLMObject
, you should use its realm
property. This way, if you decide to change the location of your realm at some point, your code inside your RLMObject
will continue to work.
Also, rather than create an extension on RLMArray
to add map, you could use Swift's free map
function.
map(videoAssets) { ($0 as RLMMediaAsset).getMediaAsset() }
这篇关于领域崩溃与RLMException:对象已被删除或无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!