iOS   发布时间:2022-03-30  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了iOS 8核心数据堆栈 – 致命错误:在解包可选值时发现为零大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我对iOS开发相对较新,决定实现自己的Core Data堆栈,取代Apple的认堆栈.

我必须在我的代码中进行更改(显然)并且能够解决它,但是在这种情况下我不能.这是我的代码

import UIKit
import CoreData

class AddTableViewController: UITableViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {

    @IBOutlet weak var nameTextField:UITextField!
    @IBOutlet weak var LOCATIOntextField:UITextField!
    @IBOutlet weak var imageView:UIImageView!
    @IBOutlet weak var notesView:UITextView!

    var coreDataStack = (UIApplication.sharedApplication().delegate as AppDelegatE).coreDataStack

    var BACkpackerSpot:BACkpackerSpot!
    var managedContext: NsmanagedObjectContext!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // TODO Give user the choice of the Photo Library or the Camera
    override func tableView(tableView: UITableView,didSELEctRowATindexPath indexPath: NSIndexPath) {
        if indexPath.row == 0 {
            if UIImagePickerController.issourceTypeAvailable(.Camera) {
                let imagePicker = UIImagePickerController()
                imagePicker.allowsEdiTing = false
                imagePicker.delegate = self
                imagePicker.sourCEType = .Camera

                self.presentViewController(imagePicker,animated: true,completion: nil)
            }
        }

        tableView.deSELEctRowATindexPath(indexPath,animated: truE)
    }

    // FIXME image is being displayed in landscape if it is taken in porTrait mode by default
    func imagePickerController(picker: UIImagePickerController!,didFinishPickingImage image: UIImage!,ediTingInfo: [NSObject : AnyObject]!) {
        imageView.image = image
        imageView.contentMode = UIViewContentMode.ScaleAspectFill
        imageView.clipsToBounds = true

        dismissviewControllerAnimated(true,completion: nil)
    }

    @IBACtion func save() {

        //validation
        var errorField = ""

        // TODO have placeholder text in the NOTES field match up with the placholder text in the NAME and LOCATION fields.
        if nameTextField.text == "" {
            errorField = "name"
        } else if LOCATIOntextField.text == "" {
            errorField = "LOCATIOn"
        } else if notesView.text == "" {
            errorField = "notes"
        }

        if errorField != "" {

            let alertController = UIAlertController(title: "Error",message: "You must fill in \(errorField).",preferredStyle: .Alert)
            let doneAction = UIAlertAction(title: "OK",style: .Default,handler: nil)
            alertController.addAction(doneAction)

            self.presentViewController(alertController,completion: nil)

            return
        }

        // If all fields are correctly filled in,extract the field value
        // Create Restaurant Object and save to data store
//        if let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegatE).coreDataStack.context {

            let entityBACkpackerSpot = NSEntityDescription.entityForName("BACkpackerSpot",inManagedObjectContext: coreDataStack.context)

            BACkpackerSpot?.spotName = nameTextField.text
            BACkpackerSpot?.spotLOCATIOn = LOCATIOntextField.text
            BACkpackerSpot?.spotImage = UIImagePNGRepresentation(imageView.imagE)
            BACkpackerSpot?.spotNote = notesView.text

            var error: NSError?
            if !managedContext.save(&error) {
                println("insert error: \(error!.localizedDescription)")
                return
            }
        // Execute the unwind segue and go BACk to the home screen
        performSegueWithIdentifier("unwindToHomeScreen",sender: self)
    }

}

该应用程序启动正常,但是当我点击附加到保存功能的UIButton时,它崩溃了,我收到以下错误

Fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)

调试器突出显示的行是:

if !managedContext.save(&error) {

不可否认,我必须花更多时间在Swift中使用Optionals,因为它们似乎常常给我带来麻烦,尽管通常我能够弄明白.如果有人能指出我正确的方向,这将是伟大的.谢谢.

编辑:这是我的核心数据栈:

import Foundation
import CoreData

class CoreDataStack {

    let model: NsmanagedObjectModel
    let storeCoordinator: NSPersistentStoreCoordinator
    let context: NsmanagedObjectContext
    let store: NSPersistentStore?

    let dbname = "BACkpackerSpots"
    // these options do the migration for us
    let options = [NSInferMappingModelAutomaticallyOption:true,NSMigratePersistentStoresAutomaticallyOption: true]

    init() {

        //1 loading model from the file
        let bundle = NSBundle.mainBundle()
        let modelURL = bundle.URLForresource(dbName,withExtension: "momd")
        model = NsmanagedObjectModel(contentsOfURL: modelURL!)!

        //2 store coordinator created using that model
        storeCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)

        //3 context
        context = NsmanagedObjectContext()
        context.persistentStoreCoordinator = storeCoordinator

        //4. store
        let documentsURL = MyDocumentDirectory()
        let storeURL = documentsURl.URLByAppendingPathComponent(dbName)

        var error:NSError?

        store = storeCoordinator.addPersistentStoreWithType(NSsqliteStoreType,configuration: nil,URL: storeURL,options: nil,error: &error)

        if store == nil {
            println("error adding persistent store: \(error)")
            abort()
        }
    }

    func saveContext() {
        var error: NSError?

        if context.hasChanges && !context.save(&error) {
            println("Could not save. \(error),\(error?.description)")
        }
    }

}

编辑:这是我的根视图控制器:

import UIKit
import CoreData

class BACkpackerSpotTableViewController: UITableViewController,NSFetchedResultsControllerDelegate {

    var coreDataStack = (UIApplication.sharedApplication().delegate as AppDelegatE).coreDataStack

//    var BACkpackerSpot:BACkpackerSpot!
    var managedContext: NsmanagedObjectContext!

    var BACkpackerSpots:[BACkpackerSpot] = []

    var fetchResultController:NSFetchedResultsController!

    // Let's add some animations!
    override func tableView(tableView: UITableView,willDisplayCell cell: UITableViewCell,forRowATindexPath indexPath: NSIndexPath) {
        // initial cell state
        cell.alpha = 0

        // state after animations
        UIView.animateWithDuration(1.0,animations: { cell.alpha = 1})
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        var fetchrequest = NSFetchrequest(entityName: "BACkpackerSpot")
        let sortDescriptor = NSSortDescriptor(key: "spotName",ascending: truE)
        fetchrequest.sortDescriptors = [sortDescriptor]

//        if let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegatE).coreDataStack {

        let entityBACkpackerSpot = NSEntityDescription.entityForName("BACkpackerSpot",inManagedObjectContext: coreDataStack.context)

            fetchResultController = NSFetchedResultsController(fetchrequest: fetchrequest,managedObjectContext: coreDataStack.context,sectionNameKeyPath: nil,cachename: nil)
            fetchResultController.delegate = self

            var error: NSError?

            var result = fetchResultController.performFetch(&error)
            BACkpackerSpots = fetchResultController.fetchedObjects as [BACkpackerSpot]

            if result != true {
                println(error?.localizedDescription)
            }
        }





    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Table view data source

    override func tableView(tableView: UITableView,numberOfRowsInSection section: int) -> Int {
        return self.BACkpackerSpots.count
    }


    override func tableView(tableView: UITableView,cellForRowATindexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cellIdentifier = "Cell"
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier,forIndexPath: indexPath) as CustomTableViewCell


        let BACkpackerSpot = BACkpackerSpots[indexPath.row]
        cell.nameLabel.text = BACkpackerSpot.spotName
        cell.thumbnailImageView.image = UIImage(data: BACkpackerSpot.spotImagE)
        cell.LOCATIOnLabel.text = BACkpackerSpot.spotLOCATIOn


        return cell
    }

    override func tableView(tableView: UITableView,commitEdiTingStyle ediTingStyle: UITableViewCellEdiTingStyle,forRowATindexPath indexPath: NSIndexPath) {


    }


    override func tableView(tableView: UITableView,editActionsForRowATindexPath indexPath: NSIndexPath) -> [AnyObject]? {


        var deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default,title: "delete",handler: {
            (action:UITableViewRowAction!,indexPath:NSIndexPath!) -> Void in


//            if let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegatE).managedObjectContext {
           let entityBACkpackerSpot = NSEntityDescription.entityForName("BACkpackerSpot",inManagedObjectContext: self.coreDataStack.context)

                let BACkpackerSpotTodelete = self.fetchResultController.objectATindexPath(indexPath) as BACkpackerSpot
                self.managedContext.deleteObject(BACkpackerSpotToDelete)

                var error: NSError?
                if !self.managedContext.save(&error) {
                    println("Could not save \(error),\(error?.description)")
                }


        })
        deleteAction.BACkgroundColor = UIColor(red: 169.0/255.0,green: 37.0/255.0,blue:
            50.0/255.0,alpha: 1.0)
        return [deleteAction]
    }

    func controllerWillChangeContent(controller: NSFetchedResultsController!) {
        tableView.beginupdates()
    }

    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:
            tableView.reloadRowsATindexPaths([indexPath],withRowAnimation: .FadE)

        default:
            tableView.reloadData()
        }

        BACkpackerSpots = controller.fetchedObjects as [BACkpackerSpot]
    }

    func controllerDidChangeContent(controller: NSFetchedResultsController!) {
        tableView.endupdates()
    }

    override func prepareForSegue(segue: UIStoryboardSegue,sender: AnyObject!) {
        if segue.identifier == "showBACkpackerSpotDetails" {
            if let row = tableView.indexPathForSELEctedRow()?.row {
                let desTinationController = segue.desTinationViewController as DetailViewController
                desTinationController.BACkpackerSpot = BACkpackerSpots[row]
            }
        }
    }

    @IBACtion func unwindToHomeScreen(segue: UIStoryboardSeguE) {

    }

}

解决方法

您尚未初始化NsmanagedContext变量.使用认的Core Data设置,您可以执行以下操作:

override func viewDidLoad() {
      if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
          managedContext = appDelegate.managedObjectContext
      }
 }

编辑:鉴于您的核心数据设置,您应该这样做:

override func viewDidLoad() {
      managedContext = coreDataStack.context
 }

大佬总结

以上是大佬教程为你收集整理的iOS 8核心数据堆栈 – 致命错误:在解包可选值时发现为零全部内容,希望文章能够帮你解决iOS 8核心数据堆栈 – 致命错误:在解包可选值时发现为零所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。