NSKeyedArchiver:关键返回nil - Swift

时间:2015-06-06 19:07:42

标签: ios swift null nskeyedarchiver

我在这里遇到一些问题。我正在尝试使用NSKeyedArchiver存储一些信息,但是当我运行应用程序时,我得到:致命错误:在解开可选值时意外发现nil

  

Apple docs说:“如果你调用其中一种解码方法   使用存档中不存在的键的类,非正数   返回值。该值因解码类型而异。例如,如果   存档中不存在密钥,decodeBoolForKey:返回NO,   decodeIntForKey:返回0, decodeObjectForKey:返回nil。

我解释对象的关键是返回nil,正如文档所说,但我不明白为什么。

这是我的代码:

import UIKit
import CoreData

class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, sendDetailsToMVCDelegate, NSFetchedResultsControllerDelegate, NSCoding {

    @IBOutlet weak var tableView: UITableView!
    var namesListArray:[String] = []
    var imagesListArray:[UIImage] = []

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.namesListArray = aDecoder.decodeObjectForKey("namesListArray") as! [String] **//HERE IS THE CRASH LINE**
        self.imagesListArray = aDecoder.decodeObjectForKey("imagesListArray") as! [UIImage]
    }

    override func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.namesListArray, forKey: "namesListArray")
        aCoder.encodeObject(self.imagesListArray, forKey: "imagesListArray")
    }

    override func viewDidLoad() {
        let dir = getUserDir()
        let archive = "\(dir)/iRecipeList-namesListArray"
        if let loaded: AnyObject = NSKeyedUnarchiver.unarchiveObjectWithFile(archive) {
            self.namesListArray = (loaded as? Array)!
        }
    }

    override func viewDidAppear(animated: Bool) {
    }

    func sendDetailsToMVC (name: String, image: UIImage) {

        namesListArray.append(name)
        let dir = getUserDir()
        let archive = "\(dir)/iRecipeList-namesListArray"
        NSKeyedArchiver.archiveRootObject(namesListArray, toFile: archive)

        imagesListArray.append(image)
        tableView.reloadData()
    }

    func getUserDir() -> String {
        let userDir = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
        return userDir[0] as! String
    }


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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let row = indexPath.row
        let name = namesListArray[row]
        println("\(row)/")
        let image = imagesListArray[row]
        var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: nil)
        cell.textLabel?.text = name
        cell.imageView!.image = image

        return cell
}

    func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        return true
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
         func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject) {
            if segue.identifier == "goToInfoVC" {
                if let navigation = navigationController {
                    navigation.popViewControllerAnimated(true)
                }
            }
        }
    }
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "newReciep" {
            var vc = segue.destinationViewController as! DetailsViewController
            vc.delegateDetails = self
        }
    }
}

有人有任何想法吗?提前谢谢!

Error pic

编辑1 enter image description here

2 个答案:

答案 0 :(得分:3)

将init更改为:

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    if let namesList = aDecoder.decodeObjectForKey("namesListArray") as? [String] {
        namesListArray = namesList
    } else {
        namesListArray = [String]
    }
    ...
}

答案 1 :(得分:0)

以下是解决方案的完整代码:

导入UIKit 导入CoreData

类MainViewController:UIViewController,UITableViewDataSource,UITableViewDelegate,sendDetailsToMVCDelegate,NSFetchedResultsControllerDelegate,NSCoding {

@IBOutlet weak var tableView: UITableView!
var namesListArray:[String] = []
var imagesListArray:[UIImage] = []

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    if let namesList = aDecoder.decodeObjectForKey("namesListArray") as? [String] {
        namesListArray = namesList
    } else {
        namesListArray = [String]()
    }
    if let imagesList = aDecoder.decodeObjectForKey("imagesListArray") as? [UIImage] {
        imagesListArray = imagesList
    } else {
        imagesListArray = [UIImage]()
    }
}

override func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(self.namesListArray, forKey: "namesListArray")
    aCoder.encodeObject(self.imagesListArray, forKey: "imagesListArray")
}

override func viewDidLoad() {
    let dir = getUserDir()
    let archiveName = "\(dir)/iRecipeList-namesListArray"
    if let loaded: AnyObject = NSKeyedUnarchiver.unarchiveObjectWithFile(archiveName) {
        self.namesListArray = (loaded as? [String])!
    }
    let archiveImage = "\(dir)/iRecipeList-imagesListArray"
    if let loaded: AnyObject = NSKeyedUnarchiver.unarchiveObjectWithFile(archiveImage) {
        self.imagesListArray = (loaded as? [UIImage])!
    }

}

override func viewDidAppear(animated: Bool) {
}

func sendDetailsToMVC (name: String, image: UIImage) {

    namesListArray.append(name)
    imagesListArray.append(image)

    let dir = getUserDir()
    let archiveName = "\(dir)/iRecipeList-namesListArray"
    NSKeyedArchiver.archiveRootObject(namesListArray, toFile: archiveName)
    let archiveImage = "\(dir)/iRecipeList-imagesListArray"
    NSKeyedArchiver.archiveRootObject(imagesListArray, toFile: archiveImage)

    tableView.reloadData()
}

func getUserDir() -> String {
    let userDir = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
    return userDir[0] as! String
}


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

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let row = indexPath.row
    let name = namesListArray[row]
    println("\(row)/")
    let image = imagesListArray[row]
    var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: nil)
    cell.textLabel?.text = name
    cell.imageView!.image = image

    return cell

}

func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return true
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
     func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject) {
        if segue.identifier == "goToInfoVC" {
            if let navigation = navigationController {
                navigation.popViewControllerAnimated(true)
            }
        }
    }
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "newReciep" {
        var vc = segue.destinationViewController as! DetailsViewController
        vc.delegateDetails = self
    }
}

}

谢谢大家!