我正在解析来自此data source的数据,并且它们被正确解析,然后我将数据(标题,价格和日期)保存到CoreData,标题保存并正确读取,价格和保存日期,但在阅读时发现它们为零。 错误是"致命错误:在展开可选值时意外发现nil"返回结果函数读取。 这是MyTableViewController.swift:
import UIKit
import CoreData
class MyTableViewController: UITableViewController {
@IBOutlet var songsTable: UITableView!
let viewModel = ViewModel()
var imageCache = [String:UIImage]()
var songs = [NSManagedObject]()
let firstDefaults = NSUserDefaults.standardUserDefaults()
let secondDefaults = NSUserDefaults.standardUserDefaults()
override func viewDidLoad() {
super.viewDidLoad()
self.refresh()
self.refreshControl = UIRefreshControl()
self.refreshControl?.addTarget(self, action: #selector(MyTableViewController.refresh), forControlEvents: .ValueChanged)
}
func refresh() {
viewModel.fetch {
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}
}
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.viewModel.numberOfSections()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.viewModel.numberOfItemsInSection(section)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MyTableViewCell
let integer: NSInteger = indexPath.row
if !firstDefaults.boolForKey("titlesSaved") {
saveItem(self.viewModel.titleForItemAtIndexPath(indexPath), id: integer, name: "title")
firstDefaults.setBool(true, forKey: "titlesSaved")
}
cell.songTitle.text = read(integer,item: "title") as String
//images are not displayed
cell.songImage?.image = UIImage(named: "Blank52.png")
let urlString = self.viewModel.imageForItemAtIndexPath(indexPath)
let imgURL: NSURL = NSURL(string: urlString)!
let request: NSURLRequest = NSURLRequest(URL: imgURL)
NSURLConnection.sendAsynchronousRequest(
request, queue: NSOperationQueue.mainQueue(),
completionHandler: {(response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
if error == nil {
cell.songImage.image = UIImage(data: data!)
}
})
let thumbnailURLString = self.viewModel.imageForItemAtIndexPath(indexPath)
let thumbnailURL = NSURL(string: thumbnailURLString)!
//if image is cached
if let img = imageCache[thumbnailURLString] {
cell.songImage?.image = img
print("image is cached")
}
else {
// The image isn't cached, download the img data
// We should perform this in a background thread
let request: NSURLRequest = NSURLRequest(URL: thumbnailURL)
let mainQueue = NSOperationQueue.mainQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: mainQueue, completionHandler: { (response, data, error) -> Void in
if error == nil {
// Convert the downloaded data in to a UIImage object
let image = UIImage(data: data!)
// Store the image in to our cache
self.imageCache[thumbnailURLString] = image
// Update the cell
dispatch_async(dispatch_get_main_queue(), {
if let cellToUpdate = tableView.cellForRowAtIndexPath(indexPath) as! MyTableViewCell?{
cellToUpdate.songImage?.image = image
}
})
}
else {
print("Error: \(error!.localizedDescription)")
}
})
}
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let detailsViewController: DetailsViewController = segue.destinationViewController as? DetailsViewController {
let songIndex = songsTable!.indexPathForSelectedRow
let integer: NSInteger = songIndex!.row
//if !secondDefaults.boolForKey("pricesAndDatesSaved") {
saveItem(self.viewModel.priceForItemAtIndexPath(songIndex!), id: integer, name: "price")
saveItem(self.viewModel.dateForItemAtIndexPath(songIndex!), id: integer, name: "date")
//secondDefaults.setBool(true, forKey: "pricesAndDatesSaved")
// }
detailsViewController.songPrice = read(integer,item: "price") as String
detailsViewController.songDate = read(integer,item: "date") as String
// detailsViewController.songPrice = self.viewModel.priceForItemAtIndexPath(songIndex!)
//detailsViewController.songDate = self.viewModel.dateForItemAtIndexPath(songIndex!)
}
}
func saveImage(id:Int,image:UIImage)
{
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("Song",
inManagedObjectContext: managedContext)
let options = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext:managedContext)
let newImageData = UIImageJPEGRepresentation(image,1)
options.setValue(id, forKey: "index")
options.setValue(newImageData, forKey: "image")
}
func saveItem(item:String, id:Int, name: String)
{
print("my \(name) is \(item)")
print("my id is \(id)")
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("Song",
inManagedObjectContext: managedContext)
let options = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext:managedContext)
options.setValue(id, forKey: "index")
switch name {
case "title":
options.setValue(item, forKey: "title")
case "price":
options.setValue(item, forKey: "price")
case "date":
options.setValue(item, forKey: "date")
default:
print("error in switch")
}
do{
try managedContext.save()
} catch let error as NSError{
print("could not save title \(error)")
}
}
func read(id: Int, item:String)-> NSString
{
print("my id in read func is \(id)")
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Song")
var result: NSString? = nil
do {
let results = try managedContext.executeFetchRequest(fetchRequest)
let single_result = results[id]
switch item {
case "title":
result = single_result.valueForKey("title") as? NSString
case "price":
result = single_result.valueForKey("price") as? NSString
case "date":
result = single_result.valueForKey("date") as? NSString
default:
print("error in switch in read function")
}
print ("i am reading the \(item): \(result)")
}catch let error as NSError{
print("could not fetch title \(error)")
}
return result!
}
这是DetailsViewController.swift
import UIKit
import CoreData
class DetailsViewController: UIViewController {
@IBOutlet weak var price: UILabel!
@IBOutlet weak var releaseDate: UILabel!
var song: ViewModel?
var songPrice: String = ""
var songDate: String = ""
override func viewDidLoad() {
super.viewDidLoad()
price.text = "Price = \(self.songPrice)"
print(self.songPrice)
print(self.songDate)
releaseDate.text = "Release date is: \(self.songDate)"
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
答案 0 :(得分:1)
您正在执行以下操作:
想要做的是:
或者更好:
您正在获得nil
,因为您为每次传递创建 THREE 对象而不是 ONE 对象。