NSEntityDescription 在展开可选值时返回 nil

Posted

技术标签:

【中文标题】NSEntityDescription 在展开可选值时返回 nil【英文标题】:NSEntityDescription returning nil while unwrapping an optional value 【发布时间】:2015-05-28 00:14:05 【问题描述】:

这就是正在发生的事情:我是 swift 新手,我还不太了解 CoreData,但我正在关注 youtube 上的一些教程,以便学习它。现在,当我运行我的应用程序时,它会崩溃,然后出现错误“致命错误:在展开可选值时意外发现 nil”

详细信息:此代码来自一个帮助新手快速使用 CoreData 的教程。

代码如下:

导入 UIKit 导入核心数据

类 SwiftCoreDataHelper: NSObject

class func directoryForDatabaseFilename()->NSString
    return NSHomeDirectory().stringByAppendingString("/Library/Private Documents")



class func databaseFilename()->NSString
    return "database.sqlite";



class func managedObjectContext()->NSManagedObjectContext

    var error:NSError? = nil

    NSFileManager.defaultManager().createDirectoryAtPath(SwiftCoreDataHelper.directoryForDatabaseFilename() as String, withIntermediateDirectories: true, attributes: nil, error: &error)

    let path:NSString = "\(SwiftCoreDataHelper.directoryForDatabaseFilename()) + \(SwiftCoreDataHelper.databaseFilename())"

    let url:NSURL = NSURL(fileURLWithPath: path as String)!

    let managedModel:NSManagedObjectModel = NSManagedObjectModel.mergedModelFromBundles(nil)!

    var storeCoordinator:NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedModel)

    if !(storeCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error:&error ) != nil)
        if (error != nil)
            println(error!.localizedDescription)
            abort()
        
    

    var managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)

    managedObjectContext.persistentStoreCoordinator = storeCoordinator

    return managedObjectContext




class func insertManagedObject(className:NSString, managedObjectConect:NSManagedObjectContext)->AnyObject

    let managedObject:NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName(className as String, inManagedObjectContext: managedObjectConect) as! NSManagedObject

    return managedObject



class func saveManagedObjectContext(managedObjectContext:NSManagedObjectContext)->Bool
    if managedObjectContext.save(nil)
        return true
    else
        return false
    



class func fetchEntities(className:NSString, withPredicate predicate:NSPredicate?, managedObjectContext:NSManagedObjectContext)->NSArray
    let fetchRequest:NSFetchRequest = NSFetchRequest()
    let entetyDescription:NSEntityDescription = NSEntityDescription.entityForName(className as String, inManagedObjectContext: managedObjectContext)!

    fetchRequest.entity = entetyDescription
    if (predicate != nil)
        fetchRequest.predicate = predicate!
    

    fetchRequest.returnsObjectsAsFaults = false
    let items:NSArray = managedObjectContext .executeFetchRequest(fetchRequest, error: nil)!

    return items

然后,它就在这里崩溃了:

    **let entetyDescription:NSEntityDescription = NSEntityDescription.entityForName(className as String, inManagedObjectContext: managedObjectContext)!** // Crashes right here, "Thead 1: EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP,subcode=0x0)

我应该怎么做才能修复这个错误?我在这个帖子里呆了 3 天,我不知道该去哪里!

提前致谢。

更新

这是我的代码:

导入 UIKit 导入核心数据

类 MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

@IBOutlet weak var mainImage: UIImageView!
@IBOutlet weak var tableView: UITableView!
var namesListArray:NSMutableArray = NSMutableArray()



override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.


override func viewDidAppear(animated: Bool) 
    super.viewDidAppear(animated)
    loadData()


func loadData() 
    namesListArray.removeAllObjects()
    let moc:NSManagedObjectContext = SwiftCoreDataHelper.managedObjectContext()
    let results:NSArray = SwiftCoreDataHelper.fetchEntities(NSStringFromClass(Recipe), withPredicate: nil, managedObjectContext: moc)
    for recipe in results 
        let singleRecipe:Recipe = recipe as! Recipe
        let recipeDict:NSDictionary = ["identifier":singleRecipe.identifier, "recipelabel":singleRecipe.recipelabel, "recipeimage":singleRecipe.recipeimage]
        namesListArray.addObject(recipeDict)
    
    tableView.reloadData()     

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return namesListArray.count


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    let cell:CustomCellTableViewCell = tableView.dequeueReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! CustomCellTableViewCell
    let recipeDict:NSDictionary = namesListArray.objectAtIndex(indexPath.row) as! NSDictionary
    let recipeName = recipeDict.objectForKey("recipelabel") as! String
    let imageData:NSData = recipeDict.objectForKey("recipeimage") as! NSData
    let recipeImage: UIImage = UIImage(data: imageData)!
    cell.customLabel.text = recipeName
    var recipeImageFrame:CGRect = cell.customImage.frame
    recipeImageFrame.size = CGSizeMake(75,75)
    cell.customImage.frame = recipeImageFrame
    cell.customImage.image = recipeImage

    return cell

谓词 NSPredicate?无 无

也许错误就在这里?如果是这样,我看不到它。有什么想法吗?

再次感谢!!!

【问题讨论】:

【参考方案1】:

传入的className 很可能有错字,因此您无法从模型中检索实体。将传入的内容与模型所期望的内容进行比较,您会发现错误。

更新

在该方法中打印出类名。打印出来的是什么?它与模型中的内容匹配吗?类名很少与实体名相同。

【讨论】:

找不到错误:(对上面的代码有什么想法吗?【参考方案2】:

我遇到了类似的错误。对我有用的是,在您的实体“配方”中尝试添加以下内容

@objc(配方) 类配方:NSManagedObject ...

您正在将配方暴露给 Objective-C。 我正在使用 Xcode 7.3.1。

还有一件事要检查。 确保您的数据模型检查器中的模块字段为空白。要到达那里,请单击您的 .xcdatamodelId 并在右侧窗格中。

【讨论】:

以上是关于NSEntityDescription 在展开可选值时返回 nil的主要内容,如果未能解决你的问题,请参考以下文章

UIPickerView:在展开可选值时意外发现 nil

致命错误:在展开可选值时意外发现 nil - 为啥?

Nil 同时展开一个实际具有值的可选

prepareForSegue 出错“”在展开可选值时意外发现 nil“”

Swift 中的可选类型错误:致命错误:在展开可选值时意外发现 nil

在展开可选值 (UIButton) 时意外发现 nil