Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialjc laurent
6,351 Pointsfatal error: unexpectedly found nil while unwrapping an Optional value
hi, In this course I get : fatal error: unexpectedly found nil while unwrapping an Optional value. At line 28 in the interactivestory.swift even I have addtarget the second Button in PageController.swift I get var artWork:UIImage { return UIImage(named: self.rawValue)! } followed by that nasty error Thread 1: EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP,subcode=0x0)
11 Answers
Moritz Lang
25,909 PointsHi,
are you sure that it should be self.rawValue
? I can not think of any usage for an image named after the rawValue of it's parent ViewController.
If your answer is yes you could please print out self.rawValue
and write what you get.
jc laurent
6,351 PointsHi, here we are: Optional(<UIImage: 0x7ffefe62f300>, {320, 568}) Optional(<UIImage: 0x7ffefe4aa970>, {320, 568}) Optional(<UIImage: 0x7fff0021b410>, {320, 568}) Optional(<UIImage: 0x7fff002359a0>, {320, 568}) Optional(<UIImage: 0x7ffefe7006d0>, {320, 568})
Moritz Lang
25,909 PointsOkay, can you please provide all content of PageController? :)
jc laurent
6,351 Pointsimport UIKit
class PageController: UIViewController {
var page: Page?
let artWork = UIImageView()
let storyLabel = UILabel()
let firstChoiceButton = UIButton(type: .System)
let secondChoiceButton = UIButton(type: .System)
required init?(coder aDecoder: NSCoder) {
super.init(coder:aDecoder)
}
init(page:Page){
self.page = page
super.init(nibName:nil,bundle:nil)
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .whiteColor()
if let page = page {
artWork.image = page.story.artWork
let attributeString = NSMutableAttributedString(string: page.story.text)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 10
attributeString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attributeString.length))
storyLabel.attributedText = attributeString
if let firstChoice = page.firstChoice {
firstChoiceButton.setTitle(firstChoice.title, forState: .Normal)
firstChoiceButton.addTarget(self, action: #selector(PageController.loadFirstChoice), forControlEvents: .TouchUpInside)
} else {
firstChoiceButton.setTitle("play again", forState: .Normal)
firstChoiceButton.addTarget(self, action: #selector(PageController.playAgain), forControlEvents: .TouchUpInside)
}
if let secondChoice = page.secondChoice {
secondChoiceButton.setTitle(secondChoice.title, forState: .Normal)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillLayoutSubviews() {
view.addSubview(artWork)
artWork.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activateConstraints([
artWork.topAnchor.constraintEqualToAnchor(view.topAnchor),
artWork.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor),
artWork.rightAnchor.constraintEqualToAnchor(view.rightAnchor),
artWork.leftAnchor.constraintEqualToAnchor(view.leftAnchor)])
view.addSubview(storyLabel)
storyLabel.translatesAutoresizingMaskIntoConstraints = false
storyLabel.numberOfLines = 0
NSLayoutConstraint.activateConstraints([
storyLabel.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant: 16.0),
storyLabel.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor, constant: -16.0),
storyLabel.topAnchor.constraintEqualToAnchor(view.centerYAnchor, constant: -48.0)])
view.addSubview(firstChoiceButton)
firstChoiceButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activateConstraints([
firstChoiceButton.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor),
firstChoiceButton.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor, constant: -80.0)
])
view.addSubview(secondChoiceButton)
secondChoiceButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activateConstraints([
secondChoiceButton.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor),
secondChoiceButton.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor, constant: -32)
])
}
func loadFirstChoice() {
if let page = page,firstChoice = page.firstChoice {
let nextPage = firstChoice.page
let pageController = PageController(page:nextPage)
navigationController?.pushViewController(pageController, animated: true)
}
}
func loadSecondChoice() {
if let page = page,secondChoice = page.secondChoice {
let nextPage = secondChoice.page
let pageController = PageController(page:nextPage)
navigationController?.pushViewController(pageController, animated: true)
}
} func playAgain() {
navigationController?.popToRootViewControllerAnimated(true)
}
}
jc laurent
6,351 PointsI know that line making problems "secondChoiceButton.addTarget(self, action: #selector(PageController.loadSecondChoice), forControlEvents: .TouchUpInside)" when I had it to "if let secondChoice = page.secondChoice { secondChoiceButton.setTitle(secondChoice.title, forState: .Normal)"
and freezing the app in interactive story at line 28 "return UIImage(named: self.rawValue)!"
jc laurent
6,351 Pointsinteractivestory.swift : import Foundation import UIKit
enum Story: String { case ReturnTrip case TouchDown case Homeward case Rover case Cave case Crate case Monster case Droid case Home
}
extension Story {
var artWork: UIImage {
return UIImage(named: self.rawValue)!
}
var text: String {
switch self {
case .ReturnTrip:
return "On your return trip from studying Saturn's rings, you hear a distress signal that seems to be coming from the surface of Mars. It's strange because there hasn't been a colony there in years. \"Help me, you're my only hope.\""
case .TouchDown:
return "You deftly land your ship near where the distress signal originated. You didn't notice anything strange on your fly-by, behind you is an abandoned rover from the early 21st century and a small crate."
case .Homeward:
return "You continue your course to Earth. Two days later, you receive a transmission from HQ saing that they have detected some sort of anomaly on the surface of Mars near an abandoned rover. They ask you to investigate, but ultimately the decision is yours because your mission has already run much longer than planned and supplies are low."
case .Rover:
return "The rover is covered in dust and most of the solar panels are broken. But you are quite surprised to see the on-board system booted up and running. In fact, there is a message on the screen. \"Come to 28.2342, -81.08273\". These coordinates aren't far but you don't know if your oxygen will last there and back."
case .Cave:
return "Your EVA suit is equipped with a headlamp which you use to navigate to a cave. After searching for a while your oxygen levels are starting to get pretty low. You know you should go refill your tank, but there's a faint light up ahead."
case .Crate:
return "Unlike everything else around you the crate seems new and...alien. As you examine the create you notice something glinting on the ground beside it. Aha, a key! It must be for the crate..."
case .Monster:
return "You pick up the key and try to unlock the crate, but the key breaks off in the keyhole.You scream out in frustration! Your scream alerts a creature that captures you and takes you away..."
case .Droid:
return "After a long walk slightly uphill, you end up at the top of a small crater. You look around and are overjoyed to see your robot friend, Droid-S1124. It had been lost on a previous mission to Mars. You take it back to your ship and fly back to Earth."
case .Home:
return "You arrive home on Earth. While your mission was a success, you forever wonder what was sending that signal. Perhaps a future mission will be able to investigate."
}
}
}
class Page {
let story: Story
typealias Choice = (title: String,page: Page)
var firstChoice: Choice?
var secondChoice: Choice?
init(story: Story) {
self.story = story
}
} extension Page {
func addChoice(title: String,story:Story)->Page{
let page = Page(story: story)
return addChoice(title, page: page)
}
func addChoice(title:String,page:Page)->Page{
switch (firstChoice,secondChoice) {
case (.Some,.Some): break
case (.None,.None),(.None,.Some): firstChoice = (title,page)
case (.Some,.None): secondChoice = (title,page)
}
return page
}
}
struct Adventure {
static var story: Page {
let returnTrip = Page(story: .ReturnTrip)
let touchdown = returnTrip.addChoice("Stop and Investigate", story: .TouchDown)
let homeward = returnTrip.addChoice("Continue Home to Earth", story: .Homeward)
let rover = touchdown.addChoice("Explore the Rover", story: .Rover)
let crate = touchdown.addChoice("Open the Crate", story: .Crate)
homeward.addChoice("Head back to Mars", page: touchdown)
let home = homeward.addChoice("Continue Home to Earth", story: .Home)
let cave = rover.addChoice("Explore the Coordinates", story: .Cave)
rover.addChoice("Return to Earth", page: home)
cave.addChoice("Continue towards faint light", story: .Droid)
cave.addChoice("Refill the ship and explore the rover", page: rover)
crate.addChoice("Explore the Rover", page: rover)
crate.addChoice("Use the key", story: .Monster)
return returnTrip
}
}
Moritz Lang
25,909 PointsHi,
loadFirstChoice()
isn't a static method so you have to call in on an instance. Please try out self.loadFirstChoice()
instead of PageController.loadFirstChoice()
when setting the buttons target,
jc laurent
6,351 Pointsthks but that still giving me the same error
jc laurent
6,351 Pointswhat I don't get is that guy is using PageController and it's working very well
Moritz Lang
25,909 PointsAh, that could be because it's Objective-C selector syntax. I don't know but maybe because of that you have to use PageController.loadFirstChoice()
.
jc laurent
6,351 Pointswell thks Moritz anyway, we should ask that guy!
jc laurent
6,351 Pointsunfortunately there's none in that section
Moritz Lang
25,909 PointsThen use the one before it. :)
Moritz Lang
25,909 PointsOr you just download the project files on the video you stuck on and compare it to your self written code.