Am on page 112 of the PDF version with the configureCheckmark method, and for the line which starts “let label =”, the debugger reads: “fatal error: unexpectedly found nil while unwrapping an Optional value” I have configured the new label with checkmark in the storyboard, and have set its tag attribute to 1001.
import UIKit
class ChecklistViewController: UITableViewController, AddItemViewControllerDelegate {
var items: [ChecklistItem]
required init?(coder aDecoder: NSCoder) {
items = [ChecklistItem]()
let row0item = ChecklistItem()
row0item.text = "Walk the dog"
row0item.checked = false
items.append(row0item)
let row1item = ChecklistItem()
row1item.text = "Brush my teeth"
row1item.checked = true
items.append(row1item)
let row2item = ChecklistItem()
row2item.text = "Learn iOS development"
row2item.checked = true
items.append(row2item)
let row3item = ChecklistItem()
row3item.text = "Soccer practice"
row3item.checked = false
items.append(row3item)
let row4item = ChecklistItem()
row4item.text = "Eat ice cream"
row4item.checked = true
items.append(row4item)
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChecklistItem", for: indexPath)
let item = items[indexPath.row]
configureText(for: cell, with: item)
configureCheckmark(for: cell, with: item)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath:IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
let item = items[indexPath.row]
item.toggleChecked()
configureCheckmark(for: cell, with: item)
}
tableView.deselectRow(at: indexPath, animated: true)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath:IndexPath) {
items.remove(at: indexPath.row)
let indexPaths = [indexPath]
tableView.deleteRows(at: indexPaths, with: .automatic)
}
func configureCheckmark(for cell: UITableViewCell, with item: ChecklistItem) {
let label = cell.viewWithTag(1001) as! UILabel
if item.checked {
label.text = "√"
} else {
label.text = ""
}
}
func configureText(for cell: UITableViewCell, with item:ChecklistItem) {
let label = cell.viewWithTag(1000) as! UILabel
label.text = item.text
}
func addItemViewControllerDidCancel(_ controller: AddItemViewController) {
dismiss(animated: true, completion: nil)
}
func addItemViewController(_ controller: AddItemViewController, didFinishAdding item: ChecklistItem) {
let newRowIndex = items.count
items.append(item)
let indexPath = IndexPath(row: newRowIndex, section: 0)
let indexPaths = [indexPath]
tableView.insertRows(at: indexPaths, with: .automatic)
dismiss(animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddItem" {
let navigationController = segue.destination as! UINavigationController
let controller = navigationController.topViewController as! AddItemViewController
controller.delegate = self
}
}
}
Wow. thanks for the super quick reply. I’ve just been playing around with the code and I seem to have got it working? Not sure how but hey…it’s working. Thanks for your help
Okay. So I wasn’t convinced when I (somehow) managed to fix the error, so I deleted my files and started the exercise again (as I want to know how it works rather than just accepting it does)…anyway, I deleted my files and restarted the exercise, and when I get to the same point on pg 112 I get the exact same error…but this time I really have no idea what I did to fix it, or even how to fix it. Also, for (whatever reason) I can’t upload a file to this message (I get a message saying new users can’t)…anyway, below is a link to download my project…if you could have a quick look at it, it would be hugely appreciated.
So I’ve deleted the last bit of code on page 112 (change “configureCheckmark(for:with)” to go back one step and the app runs fine at that point. As soon as I add in the new code I get the error. Not sure if I’m missing a step. Do I need to link the “√” label to somewhere?
Thanks,
D.
EDIT: So I figured it out. I was being a dumbass. I put the label on the wrong view controller. The code works brilliantly. Thanks for your help
Sorry to revive this old topic, but I am having the same old problem in V6. The program crashes when I try to get it to run, and I get the message “Fatal error: Unexpectedly found nil while wrapping an Optional”. Following is my code for the ChecklistViewController:
import UIKit
class ChecklistViewController: UITableViewController, AddItemViewControllerDelegate {
var items: [ChecklistItem]
required init?(coder aDecoder: NSCoder) {
items = [ChecklistItem]()
let row0item = ChecklistItem()
row0item.text = "Walk the dog"
row0item.checked = false
items.append(row0item)
let row1item = ChecklistItem()
row1item.text = "Brush my teeth"
row1item.checked = true
items.append(row1item)
let row2item = ChecklistItem()
row2item.text = "Learn iOS development"
row2item.checked = true
items.append(row2item)
let row3item = ChecklistItem()
row3item.text = "Soccer practice"
row3item.checked = false
items.append(row3item)
let row4item = ChecklistItem()
row4item.text = "Eat ice cream"
row4item.checked = true
items.append(row4item)
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
navigationController?.navigationBar.prefersLargeTitles = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChecklistItem", for: indexPath)
let item = items[indexPath.row]
let label = cell.viewWithTag(1000) as! UILabel
label.text = item.text
configureText(for: cell, with: item)
configureCheckmark(for: cell, with: item)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
let item = items[indexPath.row]
item.toggleChecked()
configureCheckmark(for: cell, with: item)
}
tableView.deselectRow(at: indexPath, animated: true)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
items.remove(at: indexPath.row)
let indexPaths = [indexPath]
tableView.deleteRows(at: indexPaths, with: .automatic)
}
func configureText(for cell: UITableViewCell, with item: ChecklistItem) {
let label = cell.viewWithTag(1000) as! UILabel
label.text = item.text
}
func configureCheckmark(for cell: UITableViewCell, with item: ChecklistItem) {
let label = cell.viewWithTag(1001) as! UILabel
if item.checked {
label.text = "√"
} else {
label.text = ""
}
}
func addItemViewControllerDidCancel(_ controller: AddItemViewController) {
navigationController?.popViewController(animated: true)
}
func addItemViewController(_ controller: AddItemViewController, didFinishAdding item: ChecklistItem) {
let newRowIndex = items.count
items.append(item)
let indexPath = IndexPath(row: newRowIndex, section: 0)
let indexPaths = [indexPath]
tableView.insertRows(at: indexPaths, with: .automatic)
navigationController?.popViewController(animated: true)
}
// @IBAction func addItem() {
// let newRowIndex = items.count
//
// let item = ChecklistItem()
// item.text = "I am a new row"
// item.checked = false
// items.append(item)
//
// let indexPath = IndexPath(row: newRowIndex, section: 0)
// let indexPaths = [indexPath]
// tableView.insertRows(at: indexPaths, with: .automatic)
// }
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddItem" {
let controller = segue.destination as! AddItemViewController
controller.delegate = self
}
}
}
Sorry to hear that you’re still having trouble. Could you either provide the full text of the error message from the Xcode console, or better yet, provide a copy of your project so that I can test it out at my end to see what is going? That way, I can see what is going on without having to guess at whether perhaps an outlet is not connected or a few other issues that I can’t see just by looking at the provided code