Swift 3:如果let语句崩溃而不是执行else阻塞

时间:2016-10-25 00:17:25

标签: ios swift if-statement swift3

我试图弄清楚Swift 3如何使用if let语法处理解包。我的场景是我想在if let语句中从CoreData进行提取。我想在那里打开值,如果有值(不是nil),那就用它吧。如果没有值,请执行else块中的内容。似乎有意义,但根据我的经验,这不是Swift 3的想法。

注意 :没有要返回的“对象”实体。我想下拉打印“无物体”。

CODE

// How I'm making the fetch from CoreData
class func getAllObjects() -> [Object]? {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.managedObjectContext
    let fetchRequest = NSFetchRequest<Object>(entityName: "Object")
    let fetched = try! context.fetch(fetchRequest)
    return fetched
}

// Unwrapping value: How I'd do it... But Xcode didn't like...
if let fetchedObjects = WorkOrder.getAllObjects() as? [Order] {
    self.objects = fetchedObjects
}
else {
    print("No Objects")
}

// Unwrapping value: How Xcode "corrected" my code and this compiles
if let fetchedObjects = WorkOrder.getAllObjects()! as [Order]? {
    self.objects = fetchedObjects
}
else {
    print("No Objects")
}

发生什么

该应用程序崩溃。在打开选项值时发现了nil。我认为if let应该防止我的应用程序崩溃。因为如果没有任何有效的解包方法,它应该执行else块。正确?

问题

您是否知道如何让if let以我上面建议的方式行事?或表现的代码?

1 个答案:

答案 0 :(得分:3)

如果没有对象,

WorkOrder.getAllObjects()将返回一个空数组,而不是nil。由于getAllObjects返回类型[Order]的可选数组,因此您不需要向下转换,条件赋值就足够了。

如果您使用保护声明进行条件分配和isEmpty测试,您的代码将更清晰:

guard let fetchedObjects = WorkOrder.getAllObjects(), !fetchedObjects.isEmpty else {
    print("No Objects")
    return
}

print("There are \(fetchedObjects.count) work orders")  // Note, no need to unwrap as the guard statement has already done this

使用try! getAllObjects编写代码的方式永远不会返回nil;它将返回Order的一个(可能是空的)数组,否则它将崩溃。如果出现问题,您应该将getAllObjects声明为throws或至少返回nil

class func getAllObjects() -> [Object]? {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.managedObjectContext
    let fetchRequest = NSFetchRequest<Object>(entityName: "Object")
    var fetched: [Object]? = nil
    do {
        fetched = try context.fetch(fetchRequest)
    } 
    catch() {
        print("Error fetching work orders: \(error)")
    }
    return fetched
}