0

I'm trying to add a button only in code. In the Xcode Simulator it works perfectly but not on my device :

fatal error: unexpectedly found nil while unwrapping an Optional value

My code:

@IBOutlet weak var playButton: UIButton!

override func viewDidLoad() {

    super.viewDidLoad()

    let image = UIImage(named: "playButton.png") as UIImage

    playButton   = UIButton.buttonWithType(UIButtonType.System) as UIButton
    playButton.frame = CGRectMake(10, 10, 100, 100) // crash is here
    playButton.center = CGPointMake(self.frame.width/2, self.frame.height/1.7)

    playButton.addTarget(self, action: "transition:", forControlEvents: UIControlEvents.TouchUpInside)
    playButton .setBackgroundImage(image, forState: UIControlState.Normal)

    self.view?.addSubview(playButton)

}

Someone can help me?

Haox
  • 608
  • 1
  • 7
  • 23

3 Answers3

2

In the Xcode Simulator it works perfectly but not on my device

That often means that you have a mismatch between your code and the actual name of a file. The MacOS X filesystem is normally not case sensitive, while the iOS file system is case sensitive. So, if your image file is named something like PlayButton.png or playButton.PNG but you specify playButton.png, it'll generally work on the simulator but not on the device.

Make sure that the filenames in your code match the files in your project.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • Thanks! I know about case sensitivity but it's not the problem. I checked and it's ok – Haox Oct 08 '14 at 19:08
1

That makes no sense - if you are using @IBOutlet that means that your button is created in the storyboard, therefore you do NOT need to initialize it:

let image = UIImage(named: "playButton.png") as UIImage

playButton   = UIButton.buttonWithType(UIButtonType.System) as UIButton
playButton.frame = CGRectMake(10, 10, 100, 100) // crash is here
playButton.center = CGPointMake(self.frame.width/2, self.frame.height/1.7)

playButton.addTarget(self, action: "transition:", forControlEvents: UIControlEvents.TouchUpInside)
playButton .setBackgroundImage(image, forState: UIControlState.Normal)

self.view?.addSubview(playButton)

Remove all of the above code and set that up in the storyboard instead. @IBAction should be a separate method which is hooked up to your touchUpInside of your button in your storyboard.

Valentin
  • 3,272
  • 1
  • 14
  • 22
  • Thank you! I removed @IBOutlet because I want my button only in code and it works like that. – Haox Oct 08 '14 at 19:11
  • Do you know how can I add the button on a scene ? When I add my code (without @IBOutlet) on my GameScene the button doesn't appear. Do you know why ? – Haox Oct 08 '14 at 19:25
  • Haox, if you are referring to SpriteKit scene I would check http://stackoverflow.com/questions/19082202/setting-up-buttons-in-skscene answer – Valentin Oct 09 '14 at 11:11
1

"Unwrapping an optionnal value" seem to refer to the ! next to your var declaration... What if you use ? instead ?

From Swift doc

Trying to use ! to access a non-existent optional value triggers a runtime error. 
Always make sure that an optional contains a non-nil value before using ! to force-unwrap its value.

Try this:

weak var playButton : UIButton?

and add ? after it when accessing it - like you do with self.view?.addSubview or locally force unwrapp it with ! in methods where you know it has already been created

(I'm not sure though, still learning the language... :-)

Vinzzz
  • 11,746
  • 5
  • 36
  • 42