NSKeyedArchiver:密钥返回 nil - Swift
NSKeyedArchiver: key returning nil - Swift
我遇到了一些问题。我正在尝试使用 NSKeyedArchiver 存储一些信息,但是当我 运行 应用程序时,我得到:致命错误:在展开可选值 .[=15 时意外发现 nil =]
Apple docs says: "If you invoke one of the decode... methods of this
class using a key that does not exist in the archive, a non-positive
value is returned. This value varies by decoded type. For example, if
a key does not exist in an archive, decodeBoolForKey: returns NO,
decodeIntForKey: returns 0, and decodeObjectForKey: returns 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
}
}
}
有人知道吗?提前致谢!
编辑 1
将 init 更改为:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if let namesList = aDecoder.decodeObjectForKey("namesListArray") as? [String] {
namesListArray = namesList
} else {
namesListArray = [String]
}
...
}
这是包含解决方案的完整代码:
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)
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
}
}
}
我遇到了一些问题。我正在尝试使用 NSKeyedArchiver 存储一些信息,但是当我 运行 应用程序时,我得到:致命错误:在展开可选值 .[=15 时意外发现 nil =]
Apple docs says: "If you invoke one of the decode... methods of this class using a key that does not exist in the archive, a non-positive value is returned. This value varies by decoded type. For example, if a key does not exist in an archive, decodeBoolForKey: returns NO, decodeIntForKey: returns 0, and decodeObjectForKey: returns 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
}
}
}
有人知道吗?提前致谢!
编辑 1
将 init 更改为:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if let namesList = aDecoder.decodeObjectForKey("namesListArray") as? [String] {
namesListArray = namesList
} else {
namesListArray = [String]
}
...
}
这是包含解决方案的完整代码:
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)
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
}
}
}