核心数据致命错误:在解包可选值

时间:2016-04-25 18:10:03

标签: ios swift uitableview core-data fatal-error

目前遇到致命错误:在执行此行代码deliveries = employee.delievery?.allObjects as! [NSManagedObject]

时解包一个Optional值时意外发现nil

我目前正在发送另一位tableView的员工var employees : [NSManagedObject]!prepareForSegue这样的

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





    }
}

prepareForSegue之所以这样,是因为tableView我所谓的变量var employee: Employee!

一旦我转到segue,它会在DeliveryTableViewController

viewDidLoad()的这行代码崩溃

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

我的NSManagedObject看起来都是这样。

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?

}

这就是我在我的另一个viewController中设置创建新投放的关系的方式

@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!)
    employee.id = Int(employeeId.text!)


    do{
        try
        manageObjectContext.save()
        first.text = ""
        last.text = ""
        phoneNumber.text = ""
        wage.text = ""
        employeeId.text = ""
        status.text = "Success!"



    }catch let error as NSError{

        status.text = error.localizedFailureReason
    }

}

我错了吗?我已经建立了员工和交付之间的关系。我正在尝试显示我在EmployeeTableViewController点击特定员工时发送给我们的员工的交付情况。任何有关此问题的帮助都非常有用,谢谢您的时间。

我在运行时得到的信息在转到DeliveryTableViewController

后失败了

What i get after segueing to DeliveryTableViewController

1 个答案:

答案 0 :(得分:4)

虽然您的问题来源不确定,但您的编码风格是问题的一部分:

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

编写Swift代码是一种非常不安全的方法,在出现问题时无法给出答案。相反,考虑这样写:

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

通过此更改,您可以查看是否没有delievery对象,或者您对allObjects的通话是否存在问题。

继续这个,你为什么要调用allObjects? EmployeeDeliverydelievery的关系,称为NSSet。这意味着它返回allObjects。为什么要拨打if let?这只是将它变成一个数组,这只是一个集合的另一种风格。

无论如何,在Swift中强迫向下推进 BAD 应该避免,除非你完全毫无疑问地知道你每次都会得到一个对象。在这种情况下,您没有这种保证,应该使用guard letDeliveryTableViewController来确认您获得的内容。

  嘿,马库斯,我要填写一张当我选择一名员工时会发生什么情况的照片,然后转到我的var employee: Employee!

好的,这表明即使是员工也可能是零而且意外地为零。我猜你有一个像这样的实例变量:

var employee: Employee?

同样,这是Swift的一个坏习惯。你应该把它写成一个合适的选项:

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

然后在需要时打开它:

Delivery

现在您将有一个正确解开的NSFetchedResultsController对象集合分配给您的实例变量,您可以从那里显示它们。

NSFetchedResultsController

说完所有这些之后,你不应该像这样展示交货。你真的应该使用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 代替。像这样:

NSFetchedResultsController

然后使用UITableViewprepareForSegue显示送货。

  

是有道理的,所以如果你在我的EmployeeTableViewController override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { guard let identifier = segue.identifier else { fatalError("Segue without an identifier") } switch identifier { case "DelieverySegue": guard let employeeDeliveries = segue.destinationViewController as? DelieveryTableViewController 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 } } 上面看上去显然不正确,我该如何做呢。

NSFetchedResultsController

同样,我会在这里使用NSFetchedResultsController而不是数组。这就是segue的目的。

但是,如果您愿意,仍然可以使用您的阵列。我不推荐它。

此处的错误是您将String视为identifier,而不是UIStoryboardSegue。您必须从String toto = await response.Content.ReadAsStringAsync(); dynamic jsonn = JValue.Parse(toto); dynamic deserializedValue = JsonConvert.DeserializeObject(toto); foreach (var data in deserializedValue.resourceSets) { foreach (var data1 in data.resources) { foreach (var data2 in data1.point) { foreach (var data3 in data2.coordinates) { var message = new MessageDialog("Coord: " + data3.coordinates); await message.ShowAsync(); } } } } } 对象中提取{ "authenticationResultCode": "ValidCredentials", "brandLogoUri": "http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png", "copyright": "Copyright © 2016 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.", "resourceSets": [ { "estimatedTotal": 1, "resources": [ { "__type": "Location:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1", "bbox": [ 41.298164367675781, -5.2461638450622559, 51.099018096923828, 9.6006984710693359 ], "name": "France", "point": { "type": "Point", "coordinates": [ 46.637279510498047, 2.3382623195648193 ] }, "address": { "countryRegion": "France", "formattedAddress": "France" }, "confidence": "High", "entityType": "CountryRegion", "geocodePoints": [ { "type": "Point", "coordinates": [ 46.637279510498047, 2.3382623195648193 ], "calculationMethod": "Rooftop", "usageTypes": [ "Display" ] } ], "matchCodes": [ "Good" ] } ] } ], "statusCode": 200, "statusDescription": "OK", "traceId": "80d14996537e49218145ff171faeca00|BN20130533|02.00.164.1500|BN2SCH020171462, i-42be63df.us-east-1b, i-e3280660.us-east-1b, BN2SCH020201258" } ,然后将其与您期望的标识符进行比较。