fatal error: unexpectedly found nil while unwrapping an Optional value: Swift, Core Data
fatal error: unexpectedly found nil while unwrapping an Optional value: Swift, Core Data
我在线上遇到错误:
let indexPath = self.menuTable.indexPathForSelectedRow()!
。
似乎我没有从 indexPathForSelectedRow
获得值。我正在将 CSV
文件解析为 Core Data
。不确定这是否重要。我是编码新手,所以不确定我是否遗漏了一些明显的东西。
import UIKit
import CoreData
class MenuTableViewController: UITableViewController {
@IBOutlet var menuTable: UITableView!
private var menuItems:[MenuItem] = []
var fetchResultController:NSFetchedResultsController!
override func viewDidLoad() {
super.viewDidLoad()
// Load menu items from database
if let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext {
let fetchRequest = NSFetchRequest(entityName: "MenuItem")
var e: NSError?
menuItems = managedObjectContext.executeFetchRequest(fetchRequest, error: &e) as! [MenuItem]
if e != nil {
println("Failed to retrieve record: \(e!.localizedDescription)")
}
}
// Make the cell self size
self.tableView.estimatedRowHeight = 66.0
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.layoutIfNeeded()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return menuItems.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = menuTable.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! MenuTableViewCell
// Configure the cell...
cell.nameLabel.text = menuItems[indexPath.row].name
cell.detailLabel.text = menuItems[indexPath.row].detail
// cell.priceLabel.text = "$\(menuItems[indexPath.row].price as! Double)"
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("showFront", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier == "showFront")
{
var upcoming: CardFrontViewController = segue.destinationViewController as! CardFrontViewController
let indexPath = self.menuTable.indexPathForSelectedRow()!
let titleString = menuItems[indexPath.row].name
upcoming.titleStringViaSegue = titleString
self.menuTable.deselectRowAtIndexPath(indexPath, animated: true)
}
}
}
由于您实现了 tableView:didSelectRowAtIndexPath:
并且单元格连接到故事板中的 segue,因此 segue 发生了两次。第二次执行 segue 时不会有任何选择,因为您在第一次 segue 期间取消选择它。您可以通过删除 tableView:didSelectRowAtIndexPath:
的实现或通过在故事板中创建 segue 并将视图控制器本身作为源而不是单元格并保留对 segue 的手动调用来解决此问题。
我不知道这是否是问题所在,但如果您需要 indexPath,为什么还要使用自己作为发件人?
尝试:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("showFront", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier == "showFront")
{
var upcoming: CardFrontViewController = segue.destinationViewController as! CardFrontViewController
let titleString = menuItems[indexPath.row].name
upcoming.titleStringViaSegue = titleString
self.menuTable.deselectRowAtIndexPath(indexPath, animated: true)
}
}
我看到您正在使用 UITableViewController
。在 UITableViewController
中,会自动为您创建一个 UITableView
并包含所需的插座。您可以通过 self.tableView
在代码中访问它。我的猜测是您没有为名为 menuTable
的 UITableView
连接 IBOutlet
。因此,展开时为 nil 的可选值不是 indexPath
而是 UITableView
.
修复:
删除你的 IBOutlet
和任何你使用 menuTable
变量的地方,并使用 self.tableView
代替。
我在线上遇到错误:
let indexPath = self.menuTable.indexPathForSelectedRow()!
。
似乎我没有从 indexPathForSelectedRow
获得值。我正在将 CSV
文件解析为 Core Data
。不确定这是否重要。我是编码新手,所以不确定我是否遗漏了一些明显的东西。
import UIKit
import CoreData
class MenuTableViewController: UITableViewController {
@IBOutlet var menuTable: UITableView!
private var menuItems:[MenuItem] = []
var fetchResultController:NSFetchedResultsController!
override func viewDidLoad() {
super.viewDidLoad()
// Load menu items from database
if let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext {
let fetchRequest = NSFetchRequest(entityName: "MenuItem")
var e: NSError?
menuItems = managedObjectContext.executeFetchRequest(fetchRequest, error: &e) as! [MenuItem]
if e != nil {
println("Failed to retrieve record: \(e!.localizedDescription)")
}
}
// Make the cell self size
self.tableView.estimatedRowHeight = 66.0
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.layoutIfNeeded()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return menuItems.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = menuTable.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! MenuTableViewCell
// Configure the cell...
cell.nameLabel.text = menuItems[indexPath.row].name
cell.detailLabel.text = menuItems[indexPath.row].detail
// cell.priceLabel.text = "$\(menuItems[indexPath.row].price as! Double)"
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("showFront", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier == "showFront")
{
var upcoming: CardFrontViewController = segue.destinationViewController as! CardFrontViewController
let indexPath = self.menuTable.indexPathForSelectedRow()!
let titleString = menuItems[indexPath.row].name
upcoming.titleStringViaSegue = titleString
self.menuTable.deselectRowAtIndexPath(indexPath, animated: true)
}
}
}
由于您实现了 tableView:didSelectRowAtIndexPath:
并且单元格连接到故事板中的 segue,因此 segue 发生了两次。第二次执行 segue 时不会有任何选择,因为您在第一次 segue 期间取消选择它。您可以通过删除 tableView:didSelectRowAtIndexPath:
的实现或通过在故事板中创建 segue 并将视图控制器本身作为源而不是单元格并保留对 segue 的手动调用来解决此问题。
我不知道这是否是问题所在,但如果您需要 indexPath,为什么还要使用自己作为发件人?
尝试:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("showFront", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier == "showFront")
{
var upcoming: CardFrontViewController = segue.destinationViewController as! CardFrontViewController
let titleString = menuItems[indexPath.row].name
upcoming.titleStringViaSegue = titleString
self.menuTable.deselectRowAtIndexPath(indexPath, animated: true)
}
}
我看到您正在使用 UITableViewController
。在 UITableViewController
中,会自动为您创建一个 UITableView
并包含所需的插座。您可以通过 self.tableView
在代码中访问它。我的猜测是您没有为名为 menuTable
的 UITableView
连接 IBOutlet
。因此,展开时为 nil 的可选值不是 indexPath
而是 UITableView
.
修复:
删除你的 IBOutlet
和任何你使用 menuTable
变量的地方,并使用 self.tableView
代替。