0

I get this error when trying to make farmTile optional: Value of optional type Bool? not unwrapped; did you mean to use '!' or '?'?

It was working fine an hour ago.

var farmTile:SKSpriteNode!

func createFarmTile(){

    farmTile = SKSpriteNode(imageNamed: "farmtile.png")
    farmTile?.size = CGSize(width: 185, height: 195)
    farmTile?.position = CGPoint(x: -95, y: 150)
    self.addChild(farmTile!)
    farmTile?.name = "farmTile"
    farmTile.zPosition = 1

   if farmTile?.contains(touchLocation){
       print("test")
   }
}
Faysal Ahmed
  • 7,501
  • 5
  • 28
  • 50
Alan Cole
  • 33
  • 6
  • Possible duplicate of [What does "fatal error: unexpectedly found nil while unwrapping an Optional value" mean?](https://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-valu) – Prashant Tukadiya Dec 05 '17 at 08:56
  • 2
    You don't have image named **farmtile.png** check spell if already there in assest – Prashant Tukadiya Dec 05 '17 at 08:58

2 Answers2

2

farmTile?.contains(touchLocation) returns an optional Bool. You should handle the optional properly. Do something like this...

var farmTile: SKSpriteNode? // optional

func createFarmTile(){

    guard let farmTile = SKSpriteNode(imageNamed: "farmtile.png")
    else { /* do what you need to do if it is missing */ ; return }

    farmTile.size = CGSize(width: 185, height: 195)
    farmTile.position = CGPoint(x: -95, y: 150)
    self.addChild(farmTile)
    farmTile.name = "farmTile"
    farmTile.zPosition = 1
    self.farmTile = farmTile

    if farmTile.contains(touchLocation){
       print("test")
    }
}
JeremyP
  • 84,577
  • 15
  • 123
  • 161
  • is crash is because of `farmTile?.contains(touchLocation)` I think it should be `self.addChild(farmTile!)` – Prashant Tukadiya Dec 05 '17 at 09:22
  • @PrashantTukadiya No. My code unwraps the return from `SKSpriteNode` so you do not need `?` or `!` in the subsequent code. – JeremyP Dec 05 '17 at 09:47
  • it is crashing because "farmtile.png" does not exist – Knight0fDragon Dec 05 '17 at 12:18
  • 1
    @Knight0fDragon Because he force unwraps `farmTile` when it is `nil`. My answer doesn't do that. – JeremyP Dec 05 '17 at 12:20
  • JeremyP, the code still fails, you just bypassed the crashing process to make the fail undetectable – Knight0fDragon Dec 05 '17 at 12:21
  • Need to address the crash first, then create the safety checks after. – Knight0fDragon Dec 05 '17 at 12:23
  • 1
    @Knight0fDragon What are you talking about? Have you read the `else` part of the guard. There's a nice comment there to put error handling in. – JeremyP Dec 05 '17 at 12:28
  • Ok, but you never address the "why" it is crashing. We are obviously dealing with a person who is very new to programming, to say "it is missing" may not have any bearing on them. Why is it crashing? Because "farmtile.png" does not exist. Make sure the spelling is correct and the asset is added correctly. After that is done, here is what you do going forward. – Knight0fDragon Dec 05 '17 at 12:30
  • 1
    @Knight0fDragon The questioner already addressed it by making the variable optional rather than implicitly unwrapped, it says so right in the title. – JeremyP Dec 05 '17 at 12:33
  • dude, you are missing the point. If the farmtile is not in his asset directory or is misspelled, then no matter how much code he puts in, his code is going to fail, and he is going to need to seek another answer to solve the question, then look to your answer to remedy future crashes. I am not sure why you are arguing this with me. – Knight0fDragon Dec 05 '17 at 12:36
  • Basically, you have part 2 of the answer, you just need to add part 1 to make it a complete answer. – Knight0fDragon Dec 05 '17 at 12:39
  • 1
    @KnightofDragon The crash was due to unexpectedly unwrapping an implicit optional that was nil. He. Has. Already. Figured. That. Out. My answer has error handling in it, but I do not prescribe any specific handling. That's up to him. – JeremyP Dec 05 '17 at 13:58
  • He has not figured it out, he has no understanding of optionals. 1st the code he provided does not even match the error he is getting, so we know the question is malformed and needs to be analyzed (His code should be crashing at `self.addChild(farmTile!)`) 2nd, he explained he made the code optional. By looking at the previous error i mentioned, I have to assume he things this means going from ! to ? on his variables. Now if I were to pop your answer into the OP code, the only result i would get is the error is hidden inside the guard statement, I would not get the solution to the problem – Knight0fDragon Dec 05 '17 at 19:13
1

The reason you are getting this error: Unexpectedly found nil while unwrapping an Optional value is because you have a nil for something that should not be nil. In your case, your farmtile is nil, but you are using SKSpriteNode! which in lay mans terms means at the time of using this variable, it better not be nil.

The only point you set farmtile is on this line farmTile = SKSpriteNode(imageNamed: "farmtile.png"), which means you have an issue with your image file because SKSpriteNode is coming back nil. I would recommend that you check to make sure you have your image file correctly set up within your assets, it is named correctly, and that it is getting bundled into your binary. If I knew how you were setting up your assets, I could further assist here.

After you solve this problem, you have another problem ahead of you. (I assume this is going to be in a different function)

if farmTile?.contains(touchLocation){
    print("test")
}

This is where you get your second error: optional: Value of optional type Bool? not unwrapped; did you mean to use '!' or '?'?

You are getting this error at compile time instead of run time because you added a ? to your farmTile thinking it will fix your problem, when it doesn't.

Now at this point you may as well correctly be handling your optionals.

You can use a guard statement to verify that the sprite is being created, and pass on a more meaningful message to yourself so that you know where the problem is in the future.

var farmTile:SKSpriteNode!

func createFarmTile(){

    guard let farmTile = SKSpriteNode(imageNamed: "farmtile.png") else { //insert your error handling here}
    farmTile.size = CGSize(width: 185, height: 195)
    farmTile.position = CGPoint(x: -95, y: 150)
    farmTile.name = "farmTile"
    farmTile.zPosition = 1
    self.farmTile = farmTile
    self.addChild(farmTile)
}

At this point we designed it so that farmTile has to exist (Basically by ensuring 100% that the createFarmTile function got called), so there is no reason to add an additional unwrap, so take out the question mark.

//Inside the touch begins function
if farmTile.contains(touchLocation){
    print("test")
}
Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44