6

I have a calculator class, a first ViewController to insert the values and a second ViewController to show the result of the calculation. Unfortunately I get a error called "Can't unwrap Optional.None" if I click the button. I know it's something wrong with the syntax, but I don't know how to improve it.

The button in the first Viewcontroller is set to "Segue: Show (e.g. Push)" in the storyboard to switch to the secondViewController if he gets tapped.

the calculator class is something like:

class Calculator: NSObject {

    func calculate (a:Int,b:Int) -> (Int) {
        var result = a * b
        return (result)
    }
}

The Viewcontroller calls the function, inserts a/b and wants to change the label which is located in the secondviewcontroller:

class ViewController: UIViewController {

@IBAction func myButtonPressed(sender : AnyObject) {
    showResult()
}

var numberOne = 4
var numberTwo = 7

var myCalc = Calculator()

func showResult () {
    var myResult = myCalc.calculate(numberOne, b: numberTwo)
    println("myResult is \(String(myResult))")
    var myVC = secondViewController()
    myVC.setResultLabel(myResult)
}

And here is the code of the secondViewController

class secondViewController: UIViewController {

@IBOutlet var myResultLabel : UILabel = nil

func setResultLabel (resultValue:Int) {
    myResultLabel.text = String(resultValue)
}

init(coder aDecoder: NSCoder!)
{
    super.init(coder: aDecoder)
}
DanielAsking
  • 333
  • 2
  • 3
  • 12
  • What is your question? – GoZoner Jun 04 '14 at 17:47
  • How are you changing between the `UIViewController`s? – 67cherries Jun 04 '14 at 17:47
  • Thank you guys, I added the information in my first post. I just realized that I had to create an instance of my class, which is now called "myVC". Unfortunately I get another error called "Can't unwrap Optional.None" now. – DanielAsking Jun 04 '14 at 17:51
  • In `showResult()` where is the value of `secondViewController` coming from? Is is a global variable? It doesn't look like an attribute in your `ViewController` class. Can you use `println()` (or the debugger) to see it's value before calling `setResultLabel()`? – GoZoner Jun 04 '14 at 17:56
  • create a custom init and pass it in there... ? – CW0007007 Jun 04 '14 at 18:02

3 Answers3

17

In Swift, everything is public by default. Define your variables outside the classes:

import UIKit

var placesArray: NSMutableArray!

class FirstViewController: UIViewController {
//
..
//
}

and then access it

import UIKit

class TableViewController: UITableViewController {
//
placesArray = [1, 2, 3]
//
}
Ramsy de Vos
  • 1,053
  • 15
  • 21
  • Thanks a lot. I was going crazy to pass the string from NSViewController to NSView of Popover and your solution saved me. – VYT May 14 '16 at 17:27
3

The problem here is that the FirstViewController has no reference to the instance of SecondViewController. Because of this, this line:

secondViewController.setResultLabel(myResult)

does nothing (except probably causing the Can't unwrap Optional.None error). There are a few ways to solve this problem. If you are using storyboard segues you can use the -prepareForSegue method of UIViewController. Here is an example:

In FirstViewController:

override func prepareForSegue(segue: UIStoryboardSegue!,sender: AnyObject!){         
  //make sure that the segue is going to secondViewController
  if segue.destinationViewController is secondViewController{
    // now set a var that points to that new viewcontroller so you can call the method correctly
    let nextController = (segue.destinationViewController as! secondViewController)
    nextController.setResultLabel((String(myResult)))
  }
}

Note: this code will not run as is because the function has no access to the result variable. you'll have to figure that out yourself :)

bkurzius
  • 4,020
  • 2
  • 34
  • 34
67cherries
  • 6,931
  • 7
  • 35
  • 51
0

I think the issue here is, you are trying to set the UI component (here, its the label : myResultLabel)

When segue is fired from first view controller, the second view has not yet been initialized. In other words, the UI object "myResultLabel" is still nil.

To solve this, you will need to create a local string variable in second controller. Now, set that string to what you are trying to display, and finally, set the actual label in "viewDidLoad()" of the second controller.

Best Regards, Gopal Nair.

Gopal Nair
  • 830
  • 4
  • 7