2017-06-13 3 views
-1

Ich erhalte diesen Wrapping-Fehler, wenn ich meinen abgerufenen verwalteten Objekt-Core-Datencode implementiere. Derzeit erhalten fatal error: unexpectedly found nil while unwrapping an Optional value. Was mache ich falsch?Schwerwiegender Fehler: beim Entpacken unerwartet ein Nullwert gefunden Optionaler Wert - Core Data (Swift)

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!") 
      } 
     } 

App Delegierter:

// 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)") 
       } 
      } 
     } 

Bitte überprüfen Screenshots enter image description here enter image description here

+1

Warum sind 'NSPersistentStoreCoordinator' und' NSManagedObjectContext' optional?Wenn die Erstellung des Koordinators fehlschlägt, erhalten Sie trotzdem einen schwerwiegenden Fehler ('abort()') und die App wird beendet. Beide Instanzen sollen ** nicht optional ** sein. Und die Init-Methode 'init (managedObjectModel' von' NSPersistentStoreCoordinator' gibt auch eine nicht-optionale Instanz zurück. Warum notieren Sie den Typ als optional und verschlechtern ihn? – vadian

+0

Aber was ist hier falsch? –

+0

Vielleicht sagt Ihnen der Compiler. – vadian

Antwort

1

Ihr managedObjectContext Objekt ist nil und Sie haben gezwungen, es mit ! gewickelt, die den Absturz verursachen wird.

Also, bevor Sie dies tun:

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

Achten Sie darauf, einen Wert für managedObjectContext haben:

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

Können Sie erklären, wie das funktioniert? –

+0

@ faig-huseynov: Ich glaube, die obige Antwort ist richtig, also abgestimmt .. Nun, wie Ihre Frage warum Warum darf ich wissen, wie Sie Zugriff auf ManagedObject Context in Ihrem VC ?? –

+0

Fragen Sie nach diesem? 'var managedObjectContext: NSManagedObjectContext?' –

-1

können Sie verwenden, wenn lassen, Sie werden also App nicht abstürzen.

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



} 

Aber für dauerhafte Lösung, bitte überprüfen Sie für Run Entity-Klasse.

0

Nach einigen Untersuchungen tun, indem Sie die Kommentare liest der Grund des Absturzes ist sehr wahrscheinlich, dass Sie nur das verwaltete Objektkontext

var managedObjectContext: NSManagedObjectContext? 

erklärt aber nicht es im View-Controller initialisiert. So bleibt es nil und verursacht den Absturz.

Ein geeigneter Weg, um den Zusammenhang von AppDelegate ist eine faule instanziiert Eigenschaft

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

Jetzt ist Ihre saveRun() Methode soll zur Arbeit zu kommen.


By the way: nicht persistentStoreCoordinator und managedObjectContext in AppDelegate als optional initialisieren. Das ist Unsinn. Die App ist nicht ausführbar und wird trotzdem beendet, wenn der Koordinator nicht erstellt werden konnte.

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 
}() 

Ein weiterer umständlich Code ist der Tanz Double-NSNumber und umgekehrt zu konvertieren. Es ist vollkommen legal, latitude und longitude in der Unterklasse als Double zu deklarieren. Das Gleiche gilt für date Attribute. Deklarieren Sie sie als Date, um eine Menge von Typ Casting zu vermeiden.

+0

Denken Sie, dass Sie persistentStoreCoordinator und managedObjectContext entfernen müssen? –

+0

Nein, nicht entfernen. Die Objekte sind notwendig (in AppDelegate). Aber deklariere sie nicht als optional. – vadian

+0

Wo deklarieren sie als optional? Ich denke, ich habe etwas verpasst, so dass es zerbröckelt –

Verwandte Themen