fizzy fizzy - 2 years ago 205
Swift Question

Core Data fatal error: unexpectedly found nil while unwrapping an Optional value

Currently getting fatal error: unexpectedly found nil while unwrapping an Optional value when executing this line of code

deliveries = employee.delievery?.allObjects as! [NSManagedObject]

I'm currently sending an employee from another
like this
var employees : [NSManagedObject]!
like this

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue == "DelieverySegue"{
let employeeDeliveries = segue.destinationViewController as! DelieveryTableViewController

let indexPath = self.tableView.indexPathForSelectedRow

let selectedEmployee = employees[indexPath!.row] as! Employee

employeeDeliveries.employee = selectedEmployee


The reason why i
like this is because the
I'm segueing to has a variable
var employee: Employee!

Once i go to segue it crashes at this line of code in my
in the

deliveries = employee.delievery?.allObjects as! [NSManagedObject]

What my
looks like for both.

extension Employee {

@NSManaged var first: String?
@NSManaged var last: String?
@NSManaged var phoneNumber: String?
@NSManaged var wage: NSNumber?
@NSManaged var id: NSNumber?
@NSManaged var delievery: NSSet?


extension Delivery {

@NSManaged var address: String?
@NSManaged var phoneNumber: String?
@NSManaged var subTotal: NSNumber?
@NSManaged var total: NSNumber?
@NSManaged var employee: Employee?


and this is how I'm setting the relationship in my other
that creates a new delivery

@IBAction func saveButton(sender: AnyObject) {

let description = NSEntityDescription.entityForName("Employee", inManagedObjectContext: manageObjectContext)

let employee = Employee(entity: (description)!, insertIntoManagedObjectContext: manageObjectContext)
employee.first = first.text
employee.last = last.text
employee.phoneNumber = phoneNumber.text
employee.wage = Float(wage.text!) = Int(employeeId.text!)

first.text = ""
last.text = ""
phoneNumber.text = ""
wage.text = ""
employeeId.text = ""
status.text = "Success!"

}catch let error as NSError{

status.text = error.localizedFailureReason


am i casting it wrong?.. i have established a relationship between Employee and Delivery already. I'm currently trying to display the deliveries of the employee i am sending when clicking on a specific employee in the
any help regarding this would be extremely helpful thank you for your time.

What i get at run time, it fails after segueing to

What i get after segueing to DeliveryTableViewController

Answer Source

While the source of your issue is undetermined by what code you have, your coding style is part of the problem:

deliveries = as! [NSManagedObject]

Is a VERY unsafe way to write Swift code and gives you no answers when things go wrong. Instead, consider writing it like this:

guard let delivery = else {
  print("Employee: \(employee)")
  fatalError("No deliver object referenced by employee")
guard let deliveries = delivery.allObjects as? [NSManagedObject] else {
  fatalError("Unexpected class type in allObjects")

With this change you can see if you don't have a delivery object or if there is an issue with your call to allObjects.

Continuing with this, why are you calling allObjects? Employee has a relationship to Delivery which is called delivery. This means that it returns an NSSet. Why call allObjects at all? That is just going to turn it into an Array which is just another flavor of a collection.

In any event, force downcasting in Swift is BAD and should be avoided unless you know absolutely without a doubt that you will get an object back every single time. In this situation, you do not have that guarantee and should either be using an if let or guard let to confirm what you are getting.

hey Marcus I'm gonna up load a picture of what happens when i select an employee and segue over to my DeliveryTableViewController

Ok, this is showing that even the employee can be nil and is unexpectedly nil. I am guessing you have an instance variable like this:

var employee: Employee!

Again, this is a bad habit in Swift. You should write it as a proper optional:

var employee: Employee?

Then unwrap it when you need it:

guard let empl = employee else {
  fatalError("Employee not set")
guard let delivery = else {
  print("Employee: \(employee)")
  fatalError("No deliver object referenced by employee")
deliveries = delivery

And now you will have a properly unwrapped collection of Delivery objects assigned to your instance variable and you can display them from there.


Having said all of that, you should not be displaying the deliveries like this. You really should be using an NSFetchedResultsController instead. Something like this:

guard let emp = employee else {
    fatalError("Employee not assigned")
let fetch = NSFetchRequest(entityName: "Delivery")
fetch.predicate = NSPredicate(format: "employee == %@", emp)

let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetch, context: emp.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

//Finish implementing the NSFetchedResultsController

Then use the NSFetchedResultsController to display the deliveries in your UITableView.

makes sense so how would i do so if you look above in my EmployeeTableViewController prepareForSegue thats obviously not correct.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    guard let identifier = segue.identifier else { 
        fatalError("Segue without an identifier")
    switch identifier {
    case "DeliverySegue":
        guard let employeeDeliveries = segue.destinationViewController as? DeliveryTableViewController else {
            fatalError("Unexpected view controller class")
        guard let indexPath = self.tableView.indexPathForSelectedRow else {
            fatalError("No row selected")
        let employee = fetchedResultsController.objectAtIndexPath(indexPath)
        //Use a NSFetchedResultsController here also
        //let selectedEmployee = employees[indexPath!.row] as! Employee
        employeeDeliveries.employee = employee
    default: break

Again, I would be using an NSFetchedResultsController here as well instead of an array. This is what the NSFetchedResultsController is designed for.

However, you can still use your array if you choose. I would not recommend it.

The error here is that you are treating segue as a String when it is not. You must extract the identifier from UIStoryboardSegue object and then compare that against the identifier you are expecting.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download