在强制展开可选的 swift 2 时发现 nil
Posted
技术标签:
【中文标题】在强制展开可选的 swift 2 时发现 nil【英文标题】:Found nil while force unwrapping an optional swift 2 【发布时间】:2015-11-27 15:07:41 【问题描述】:我在展开可选值时不断收到错误消息,提示发现 nil。我不知道为什么会这样做,因为数据是从另一个视图控制器存储到变量中的,但它没有分配新值,而是将其保持为零。为什么要这样做?任何帮助将不胜感激。
注意:它在 userEventViewController 的第 47 行崩溃
在线崩溃:myTitle.title = event!.name
项目链接:https://www.dropbox.com/s/1d4d8opuxzpcuk4/TicketekApp.zip?dl=0
代码:
源视图控制器(EventTableViewController):
// EventTableViewController.swift
import UIKit
class EventTableViewController: UITableViewController
// MARK: Properties
var currentlySelectedIndex = 0
var events = [Event]()
var isAdmin: Bool = false
var currentUser: String = ""
override func viewDidLoad()
super.viewDidLoad()
print(currentUser)
// Use the edit button item provided by the table view controller.
if isAdmin == true
navigationItem.leftBarButtonItem = editButtonItem()
// Load any saved events, otherwise load sample data.
if let savedEvents = loadEvents()
events += savedEvents
else
// Load the sample data.
loadSampleEvents()
func loadSampleEvents()
let photo1 = UIImage(named: "event1")!
let event1 = Event(name: "ACDC", photo: photo1, rating: 4, price: 100.0, eventDescription: "AC/DC are an Australian hard rock band, formed in November 1973 by brothers Malcolm and Angus Young, who continued as members until Malcolm's illness and departure in 2014. Date of Event: 1/3/16", album: "Redemption Tour")!
let photo2 = UIImage(named: "event2")!
let event2 = Event(name: "Cold Play", photo: photo2, rating: 5, price: 150.0, eventDescription: "Coldplay are a British rock band formed in 1996 by lead vocalist Chris Martin and lead guitarist Jonny Buckland at University College London. Date of Event: 12/12/15", album: "Mylo Xyloto")!
let photo3 = UIImage(named: "event3")!
let event3 = Event(name: "One Direction", photo: photo3, rating: 3, price: 120.0, eventDescription: "One Direction are an English-Irish pop boy band based in London, composed of Niall Horan, Liam Payne, Harry Styles, Louis Tomlinson, and previously, Zayn Malik until his departure from the band on 25 March 2015. Date of Event: 5/9/16", album: "Made in the A.M.")!
events += [event1, event2, event3]
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 1
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return events.count
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "EventTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! EventTableViewCell
// Fetches the appropriate event for the data source layout.
let event = events[indexPath.row]
cell.nameLabel.text = event.name
cell.photoImageView.image = event.photo
cell.ratingControl.rating = event.rating
cell.priceLabel.text = event.album
return cell
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
//Record the row selected
currentlySelectedIndex = indexPath.row
//check for admin
if isAdmin == true
performSegueWithIdentifier("eventViewControllerSegue", sender: self)
else
performSegueWithIdentifier("userEventViewControllerSegue", sender: self)
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
// Return false if you do not want item to be editable.
if isAdmin == true
return true
else
return false
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
if isAdmin == true
if editingStyle == .Delete
// Delete the row from the data source
events.removeAtIndex(indexPath.row)
saveEvents()
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
else if editingStyle == .Insert
// Create new instance of class, add to the array, and add a new row to the table
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
*/
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool
// Return false if you do not want the item to be re-orderable.
if isAdmin == true
return true
else
return false
// MARK: - Navigation
// preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
if segue.identifier == "eventViewControllerSegue"
let destinationVC1 = segue.destinationViewController as? EventViewController
destinationVC1!.event = events[currentlySelectedIndex]
else if segue.identifier == "userEventViewControllerSegue"
let eventDetailViewController = segue.destinationViewController as! UserEventViewController
//Get the associated event
eventDetailViewController.event = events[currentlySelectedIndex]
let destinationVC = segue.destinationViewController as? UserEventViewController
destinationVC!.event = events[currentlySelectedIndex]
destinationVC!.currentUser = currentUser
else if segue.identifier == "AddItem"
print("Adding new event.")
@IBAction func unwindToMealList(sender: UIStoryboardSegue)
if let sourceViewController = sender.sourceViewController as? EventViewController, event = sourceViewController.event
if let selectedIndexPath = tableView.indexPathForSelectedRow
// Update an existing event.
events[selectedIndexPath.row] = event
tableView.reloadRowsAtIndexPaths([selectedIndexPath], withRowAnimation: .None)
else
// Add a new event.
let newIndexPath = NSIndexPath(forRow: events.count, inSection: 0)
events.append(event)
tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
// Save the events.
saveEvents()
// MARK: NSCoding
func saveEvents()
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(events, toFile: Event.ArchiveURL.path!)
if !isSuccessfulSave
print("Failed to save events...")
func loadEvents() -> [Event]?
return NSKeyedUnarchiver.unarchiveObjectWithFile(Event.ArchiveURL.path!) as? [Event]
目标视图控制器(userEventViewController):
// EventViewController.swift
import UIKit
class UserEventViewController: UIViewController
// MARK: Properties
@IBOutlet weak var eventDescriptionLabel: UITextView!
@IBOutlet weak var priceLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var photoImageView: UIImageView!
@IBOutlet weak var albumNameLabel: UILabel!
@IBOutlet weak var myTitle: UINavigationItem!
@IBOutlet weak var ratingControl: RatingControl!
var event: Event?
var currentUser: String = ""
override func viewDidLoad()
super.viewDidLoad()
// Set up views if editing an existing event.
// |
// Crashes on this line \./
myTitle.title = event!.name
nameLabel.text = event!.name
photoImageView.image = event!.photo
ratingControl.rating = event!.rating
eventDescriptionLabel.text = event!.eventDescription
albumNameLabel.text = event!.album
priceLabel.text = String(event!.price)
print(currentUser)
@IBAction func buyTickets(sender: AnyObject)
performSegueWithIdentifier("BuyTickets", sender: self)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
if segue.identifier == "BuyTickets"
let destinationVC = segue.destinationViewController as? seatsPickerViewController
destinationVC!.price = event!.price
destinationVC!.name = event!.name
destinationVC!.album = event!.album
destinationVC!.photo = event!.photo
destinationVC!.currentUser = currentUser
【问题讨论】:
在哪一行崩溃? userEventViewController @luk2302 第 47 行 好吧,要么在源代码中包含行号(不推荐),要么告诉我们行,而不是行号,我应该如何计算 8 个空白连续几行? 抱歉,添加到@luk2302 尝试删除处理destinationVC
的三行
【参考方案1】:
您尚未连接插座:
【讨论】:
【参考方案2】:它会崩溃,因为你还没有初始化event
。你刚刚声明它是一个可选的,所以当你选择在几行之后打开它时它保持为零。我们知道,如果你试图解开 nil,你的程序就会崩溃。
给event
赋值然后试试
【讨论】:
以上是关于在强制展开可选的 swift 2 时发现 nil的主要内容,如果未能解决你的问题,请参考以下文章
Swift 1.2:致命错误:在展开可选值时意外发现 nil