fetchedResultsController 核心数据致命错误:在展开可选值时意外发现 nil
Posted
技术标签:
【中文标题】fetchedResultsController 核心数据致命错误:在展开可选值时意外发现 nil【英文标题】:fetchedResultsController core data fatal error: unexpectedly found nil while unwrapping an Optional value 【发布时间】:2015-01-30 10:09:23 【问题描述】:我知道有无数个问题都有相同的错误,但似乎没有一个解决方案有效。
我想制作一个博客阅读器应用程序,它可以从 CoreData 保存和获取数据。我可以将 JSON 结果保存到 CoreData 中,但是当我尝试检索它以显示在 tableView 中时,它会因在线 fatal error: unexpectedly found nil while unwrapping an Optional value
而崩溃
let entity = NSEntityDescription.entityForName("Blog", inManagedObjectContext:self.managedObjectContext!)
这是我的代码:
import UIKit
import CoreData
var activeItem:String = ""
class CenterViewController: UIViewController,
UIWebViewDelegate, NSFetchedResultsControllerDelegate,
SidePanelViewControllerDelegate
var detailViewController: DetailViewController? = nil
var managedObjectContext: NSManagedObjectContext? = nil
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var tableview: UITableView!
@IBOutlet weak var webview2: UIWebView!
var delegate: CenterViewControllerDelegate?
// MARK: Button actions
@IBAction func kittiesTapped(sender: AnyObject)
delegate?.toggleLeftPanel?()
@IBAction func puppiesTapped(sender: AnyObject)
delegate?.toggleRightPanel?()
func animalSelected(animal: Animal)
var appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
var context: NSManagedObjectContext = appDel.managedObjectContext!
var newBlogItem:NSManagedObject
let session = NSURLSession.sharedSession()
var error : NSError?
let task = session.dataTaskWithURL(animal.url!, completionHandler: data, response, error -> Void in
if (error != nil)
println(error)
else
let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
var posts = [[String:String]()]
var post:AnyObject
var authorDictionary:AnyObject
var newBlogItem:NSManagedObject
for var i = 0; i < jsonResult["posts"]!.count; i++
posts.append([String:String]())
post = jsonResult["posts"]![i] as NSDictionary
posts[i]["title"] = post["title"] as? NSString
posts[i]["publishedDate"] = post["date"] as? NSString
posts[i]["content"] = post["content"] as? NSString
authorDictionary = post["author"] as NSDictionary
posts[i]["author"] = post["name"] as? NSString
newBlogItem = NSEntityDescription.insertNewObjectForEntityForName("Blog", inManagedObjectContext: context) as NSManagedObject
newBlogItem.setValue(posts[i]["title"], forKey: "title")
newBlogItem.setValue(posts[i]["publishedDate"], forKey: "publishedDate")
newBlogItem.setValue(posts[i]["content"], forKey: "content")
newBlogItem.setValue(posts[i]["author"], forKey: "author")
context.save(nil)
var request = NSFetchRequest(entityName: "Blog")
request.returnsObjectsAsFaults = false
var results = context.executeFetchRequest(request, error: nil)
println(results)
)
task.resume()
delegate?.collapseSidePanels?()
// MARK: - Table View
func numberOfSectionsInTableView(tableView: UITableView) -> Int
return self.fetchedResultsController.sections!.count
// return 1
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
let sectionInfo = self.fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo
return sectionInfo.numberOfObjects
//return 20
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
// self.configureCell(cell, atIndexPath: indexPath)
cell.textLabel?.text = "blog item"
return cell
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
// Return false if you do not want the specified item to be editable.
return true
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
if editingStyle == .Delete
let context = self.fetchedResultsController.managedObjectContext
context.deleteObject(self.fetchedResultsController.objectAtIndexPath(indexPath) as NSManagedObject)
var error: NSError? = nil
if !context.save(&error)
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//println("Unresolved error \(error), \(error.userInfo)")
abort()
func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath)
let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as NSManagedObject
cell.textLabel?.text = object.valueForKey("title")!.description
// MARK: - Fetched results controller
var fetchedResultsController: NSFetchedResultsController
if _fetchedResultsController != nil
return _fetchedResultsController!
let fetchRequest = NSFetchRequest()
// Edit the entity name as appropriate.
let entity = NSEntityDescription.entityForName("Blog", inManagedObjectContext:self.managedObjectContext!)
fetchRequest.entity = entity?
// Set the batch size to a suitable number.
fetchRequest.fetchBatchSize = 20
// Edit the sort key as appropriate.
let sortDescriptor = NSSortDescriptor(key: "publishedDate", ascending: false)
let sortDescriptors = [sortDescriptor]
fetchRequest.sortDescriptors = [sortDescriptor]
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: "Slide Out Tutorial")
aFetchedResultsController.delegate = self
_fetchedResultsController = aFetchedResultsController
var error: NSError? = nil
if !_fetchedResultsController!.performFetch(&error)
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//println("Unresolved error \(error), \(error.userInfo)")
abort()
return _fetchedResultsController!
var _fetchedResultsController: NSFetchedResultsController? = nil
func controllerWillChangeContent(controller: NSFetchedResultsController)
self.tableview.beginUpdates()
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
switch type
case .Insert:
self.tableview.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
case .Delete:
self.tableview.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
default:
return
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath)
switch type
case .Insert:
tableview.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
case .Delete:
tableview.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
case .Update:
self.configureCell(tableview.cellForRowAtIndexPath(indexPath)!, atIndexPath: indexPath)
case .Move:
tableview.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
tableview.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
default:
return
func controllerDidChangeContent(controller: NSFetchedResultsController)
self.tableview.endUpdates()
当我分别从numberOfSectionsInTableView
和func tableView(tableView: UITableView, numberOfRowsInSection section: Int)
返回1和返回20时,tableview显示文本“blog item”20次,数据显示在控制台中。但是当我注释掉手动返回值并想使用原始返回值时,应用程序在上面提到的行上崩溃了。
我只是猜测它是否与 fetchedResultsController
有关。
请帮忙。从昨天开始我就一直坚持这个
【问题讨论】:
你需要设置self.managedObjectContext的值,它被初始化为nil,然后永远不会设置。 @pbasdf 你能帮我解决这个问题吗..m 是 Swift 的新手,并通过混合不同的单个项目设法到达这里 【参考方案1】:您需要设置self.managedObjectContext
(它当前为 nil,这会导致您的错误)。您可以在视图控制器生命周期早期调用的函数之一中设置它,例如viewDidLoad
,但另一种方法是在初始化 fetchedResultsController 时设置它,如下所示:
var fetchedResultsController: NSFetchedResultsController
if _fetchedResultsController != nil
return _fetchedResultsController!
var appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
self.managedObjectContext = appDel.managedObjectContext
let fetchRequest = NSFetchRequest()
// Edit the entity name as appropriate.
let entity = NSEntityDescription.entityForName("Blog", inManagedObjectContext:self.managedObjectContext!)
fetchRequest.entity = entity?
...
【讨论】:
还发现我忘了实例化我的上下文,一个我没在看的地方,谢谢!! @pbasdf 哦,伙计!你刚刚救了我的命!谢谢。在调试器中,我一直在努力解决这个问题大约 8 个小时……谢谢!以上是关于fetchedResultsController 核心数据致命错误:在展开可选值时意外发现 nil的主要内容,如果未能解决你的问题,请参考以下文章
FetchedResultsController 中没有部分
如何将对象从 fetchedResultsController 到 Plist?
fetchedResultsController 对象的表视图部分
fetchedResultsController 和 Integer