2017-06-13 30 views
-1

我得到這個包裝錯誤,當我實現我提取的託管對象的核心數據代碼。目前得到fatal error: unexpectedly found nil while unwrapping an Optional value。我究竟做錯了什麼?致命錯誤:意外地發現零,而展開一個可選值 - 核心數據(斯威夫特)

的ViewController:

func saveRun() { 
      // 1 
      let savedRun = NSEntityDescription.insertNewObject(forEntityName: "Run", into: managedObjectContext!) as! Run 
      savedRun.distance = NSNumber(value: distance) 
      savedRun.duration = (NSNumber(value: seconds)) 
      savedRun.timestamp = NSDate() as Date 



      // 2 
      var savedLocations = [Location]() 
      for location in locations { 
       let savedLocation = NSEntityDescription.insertNewObject(forEntityName: "Location", 
                     into: managedObjectContext!) as! Location 
       savedLocation.timestamp = (location.timestamp as NSDate) as Date 
       savedLocation.latitude = NSNumber(value: location.coordinate.latitude) 
       savedLocation.longitude = NSNumber(value: location.coordinate.longitude) 
       savedLocations.append(savedLocation) 
      } 
      savedRun.locations = NSOrderedSet(array: savedLocations) 
      run = savedRun 

      do{ 
       try managedObjectContext!.save() 
      }catch{ 
       print("Could not save the run!") 
      } 
     } 

應用代表:

// MARK: - Core Data stack 

    lazy var applicationDocumentsDirectory: URL = { 
     // The directory the application uses to store the Core Data store file. This code uses a directory named "com.zedenem.MarathonRun" in the application's documents Application Support directory. 
     let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 
     return urls.last! 
    }() 

    lazy var managedObjectModel: NSManagedObjectModel = { 
     // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model. 
     let modelURL = Bundle.main.url(forResource: "MarathonRun", withExtension: "momd")! 
     return NSManagedObjectModel(contentsOf: modelURL)! 
    }() 

    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = { 
     // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. 
     // Create the coordinator and store 
     var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) 
     let url = self.applicationDocumentsDirectory.appendingPathComponent("MarathonRun") 
     var error: NSError? = nil 
     var failureReason = "There was an error creating or loading the application's saved data." 
     do { 
      try coordinator!.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil) 
     }catch let error as NSError { 
      coordinator = nil 
      // Report any error we got. 
      var dict = [AnyHashable: Any]() 
      dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" 
      dict[NSLocalizedFailureReasonErrorKey] = failureReason 
      dict[NSUnderlyingErrorKey] = error 

      print("Error: \(error.domain)") 
      abort() 
     } 
     return coordinator 
    }() 

    lazy var managedObjectContext: NSManagedObjectContext? = { 
     // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail. 
     let coordinator = self.persistentStoreCoordinator 
     if coordinator == nil { 
      return nil 
     } 
     var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)//NSManagedObjectContext() 
     managedObjectContext.persistentStoreCoordinator = coordinator 
     return managedObjectContext 
    }() 

    // MARK: - Core Data Saving support 

    func saveContext() { 
     if let moc = self.managedObjectContext { 
      if moc.hasChanges{ 
       do{ 
        try moc.save() 
       }catch let error as NSError{ 
        print("Error: \(error.domain)") 
       } 
      } 
     } 

請檢查截圖enter image description here enter image description here

+1

爲什麼'NSPersistentStoreCoordinator'和'NSManagedObjectContext'是可選的?如果創建協調程序失敗,則會發生致命錯誤('abort()'),並且應用程序終止。這兩個實例都應該是**非可選**。而init方法'NSPersistentStoreCoordinator'的init(managedObjectModel)也會返回一個非可選實例。爲什麼你註釋類型是可選的,並且變得更糟? – vadian

+0

但是這裏有什麼問題? –

+0

也許編譯器會告訴你。 – vadian

回答

1

managedObjectContext對象是nil,你已經用!將它包裹起來,這會導致崩潰。

你這樣做,所以才:

let savedRun = NSEntityDescription.insertNewObject(forEntityName: "Run", into: managedObjectContext!) as! Run 

確保你有一個價值managedObjectContext

if let managedObjectContext = [get the managedObjectContext object here] { 
    // If you succeed with getting the managedObjectContext, then you can use it without the ! in here 
    let savedRun = NSEntityDescription.insertNewObject(forEntityName: "Run", into: managedObjectContext) as! Run 
} 
+0

你能解釋一下這是如何工作的嗎? –

+0

@ faig-huseynov:我相信上面的答案是正確的,因此現在根據你的問題,爲什麼我可以知道你如何訪問你的VC中的managedObject上下文 –

+0

你問這個問題嗎? 'var managedObjectContext:NSManagedObjectContext?' –

-1

如果讓你可以使用,所以你的應用程序不會崩潰。

if let savedRun = NSEntityDescription.insertNewObject(forEntityName: "Run", into: managedObjectContext!) as! Run { 



} 

但是對於永久性修復,請重新檢查Run Entity類。

0

通過閱讀註釋做了一些調查後墜毀的原因是最有可能的,你是唯一的聲明被管理對象上下文

var managedObjectContext: NSManagedObjectContext? 

但不初始化它在視圖控制器。所以它仍然是nil並導致崩潰。

合適的方式來獲得AppDelegate中的背景是一個懶惰的實例屬性

lazy var managedObjectContext : NSManagedObjectContext = { 
    let appDelegate = UIApplication.shared.delegate as! AppDelegate 
    return appDelegate.managedObjectContext 
}() 

現在你saveRun()方法應該工作。


順便說一句:不要初始化的AppDelegate persistentStoreCoordinatormanagedObjectContext可選。這是無稽之談。該應用程序是不可行的,如果無法創建協調程序,它將終止。

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = { 
    // Create the coordinator and store 
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) 
    let url = self.applicationDocumentsDirectory.appendingPathComponent("MarathonRun") 
    do { 
     try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil) 
    } catch let error as NSError { 
     // Report any error we got. 
     var dict = [AnyHashable: Any]() 
     dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" 
     dict[NSLocalizedFailureReasonErrorKey] = "There was an error creating or loading the application's saved data." 
     dict[NSUnderlyingErrorKey] = error 

     print("Error: ", error) 
     abort() 
    } 
    return coordinator 
}() 

lazy var managedObjectContext: NSManagedObjectContext = { 
    let coordinator = self.persistentStoreCoordinator 
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)//NSManagedObjectContext() 
    managedObjectContext.persistentStoreCoordinator = coordinator 
    return managedObjectContext 
}() 

另一個繁瑣的代碼轉換DoubleNSNumber,反之亦然舞蹈。在NSManagedObject子類中聲明latitudelongitudeDouble是完全合法的。同樣的事情是date屬性。聲明它們爲Date以避免大量類型轉換。

+0

你認爲你需要刪除persistentStoreCoordinator和managedObjectContext嗎? –

+0

不,不刪除。對象是必需的(在AppDelegate中)。但不要聲明它們是可選的。 – vadian

+0

哪裏聲明它們是可選的? 我想我錯過了東西,所以它崩潰了 –

相關問題