使用CoreData获取时崩溃

时间:2017-07-18 15:04:36

标签: ios swift core-data nsfetchrequest

我的应用正在制作中,当我尝试将festRequest的第一个元素转换为某个实体时,我在Crashlytics上遇到了一些崩溃。无论我怎么努力,我都无法重现这次崩溃。

static func getSettings() -> NotificationSettingsMO {
  var settings: NotificationSettingsMO!

  let moc = DataController.shared.managedObjectContext

  moc.performAndWait {
    do {
      let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "NotificationSettings")
      settings = try moc.fetch(fetchRequest).first as! NotificationSettingsMO
    } catch {
    print(error)
    }
  }

  return settings

当尝试将请求的第一个元素强制转换为NotificationSettingsMO时发生崩溃,并且我确定该实体存在,因为我在创建用户时创建了该实体。这也仅发生在一小部分用户身上,但由于它会使应用程序崩溃,我想尝试找出导致它的原因。

编辑:我已附上崩溃日志

Crashed: com.apple.main-thread
0  MyApp                        0x100073360 specialized static NotificationSettingsMO.(getSettings() -> NotificationSettingsMO).(closure #1) (NotificationSettingsMO.swift:25)
1  MyApp                        0x10007309c partial apply for static NotificationSettingsMO.(getSettings() -> NotificationSettingsMO).(closure #1) (NotificationSettingsMO.swift)
2  CoreData                       0x18311d08c developerSubmittedBlockToNSManagedObjectContextPerform + 196
3  CoreData                       0x18311cf54 -[NSManagedObjectContext performBlockAndWait:] + 220
4  MyApp                        0x100072fa8 specialized static NotificationSettingsMO.getSettings() -> NotificationSettingsMO (NotificationSettingsMO.swift)
5  MyApp                        0x1000d6190 AppDelegate.getDataOnLaunch() -> () (AppDelegate.swift)
6  MyApp                        0x1000da4bc specialized AppDelegate.application(UIApplication, didFinishLaunchingWithOptions : [UIApplicationLaunchOptionsKey : Any]?) -> Bool (AppDelegate.swift:99)
7  MyApp                        0x1000d3eb8 @objc AppDelegate.application(UIApplication, didFinishLaunchingWithOptions : [UIApplicationLaunchOptionsKey : Any]?) -> Bool (AppDelegate.swift)
8  UIKit                          0x1863f29c0 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 400
9  UIKit                          0x186622184 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2904
10 UIKit                          0x1866265f0 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1684
11 UIKit                          0x186623764 -[UIApplication workspaceDidEndTransaction:] + 168
12 FrontBoardServices             0x182bbf7ac __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 36
13 FrontBoardServices             0x182bbf618 -[FBSSerialQueue _performNext] + 168
14 FrontBoardServices             0x182bbf9c8 -[FBSSerialQueue _performNextFromRunLoopSource] + 56
15 CoreFoundation                 0x1811d509c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
16 CoreFoundation                 0x1811d4b30 __CFRunLoopDoSources0 + 540
17 CoreFoundation                 0x1811d2830 __CFRunLoopRun + 724
18 CoreFoundation                 0x1810fcc50 CFRunLoopRunSpecific + 384
19 UIKit                          0x1863eb94c -[UIApplication _run] + 460
20 UIKit                          0x1863e6088 UIApplicationMain + 204
21 MyApp                        0x10001ee18 main (Measurement+Network.swift:26)
22 libdispatch.dylib              0x180c9a8b8 (Missing)

1 个答案:

答案 0 :(得分:1)

该对象不存在,因此崩溃。就个人而言,我强烈反对强行施放。可选项的重点是帮助您管理什么时候是零。将as!放入代码中会导致程序崩溃。我建议删除它并用if let替换它。如果你100%确定它永远不会是零,那么你仍然应该使用if let并在else报告中使崩溃服务崩溃(使用Crashlytics recordError - 它将显示与你的崩溃一起。)

至于你的陈述:

  

我确定实体存在,因为我在创建用户时创建它

直言不讳地说 - 你错了。计算机总是正确的,人类总是错的。

以下是可能的原因:

  • 将核心数据保存到核心数据时出错我怀疑与大多数程序一样,当您将对象保存到核心数据时,您没有检查错误 - 或者如果您这样做,那么您真的不知道如何处理错误。如果你很聪明,你会记录它。最常见的错误是硬盘上没有空间。如果对象没有保存在第一个位置,那么当你获取它时就不会存在。
  • 该对象已存在但已被删除。如果您的代码中有任何地方删除此对象,请考虑在此代码运行之前删除它的可能性。寻找多线程和竞争条件。
  • 该对象尚未保存。如果您在应用中有任何多线程,则应考虑存在竞争条件的可能性。

任何这些情况都会导致0-3%范围内的崩溃。