我有一个存储时间线的领域模型(我正在制作视频编辑应用程序),它经常会破坏访问它的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
以下是RLM项目代码:
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.invalidated
或soundtracks.invalidated
,这就是为什么堆栈跟踪显示RLMGetArray
中正在引发未捕获的异常。
这意味着在调用setTimeLineModel
之前,对象已从域中删除。请在代码中查找realm.deleteObject(_:)
,以查看可能发生的情况。
最后,一些使代码更安全、更简单的一般技巧:
您应该使用它的RLMRealm.defaultRealm()
属性,而不是在RLMObject
中的任何位置使用realm
。这样,如果您决定在某个时候更改域的位置,那么RLMObject
中的代码将继续工作。
另外,您可以使用Swift的freeRLMArray
函数,而不是在map
上创建一个扩展来添加map。
map(videoAssets) { ($0 as RLMMediaAsset).getMediaAsset() }