2

我知道有无数问题具有相同的错误,但似乎没有一个解决方案有效。

我想制作一个博客阅读器应用程序,可以从 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()
}

}

当我分别返回1和返回20时,tableview显示文本“blog item”20次 numberOfSectionsInTableViewfunc tableView(tableView: UITableView, numberOfRowsInSection section: Int)并在控制台中显示数据。但是当我注释掉手动返回值并想使用原始返回值时,应用程序在上面提到的行上崩溃了。

我只是猜测它是否与fetchedResultsController.

请帮忙。我从昨天开始就坚持这个

4

1 回答 1

5

You need to set self.managedObjectContext (it is currently nil and that is causing your error). You could set it in one of the functions called early in the life of the view controller, such as viewDidLoad, but another way would be to set it when initialising the fetchedResultsController, like this:

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?
    ...
于 2015-01-31T18:31:14.103 回答