-1

I'm making quiz app and when I want to change value of alpha of my UIView I'm getting error fatal error: unexpectedly found nil while unwrapping an Optional value, before it warms fine but I'm remodeling my app and I think that I delete something or change by mistake. I don't want to put all my code here because it is quiet large so I will cut most important parts.

import UIKit

class ViewController: UIViewController{

@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var answerStackView: UIStackView!

// Feedback screen
@IBOutlet weak var resultView: UIView!
@IBOutlet weak var dimView: UIView!
@IBOutlet weak var resultLabel: UILabel!
@IBOutlet weak var feedbackLabel: UILabel!
@IBOutlet weak var resultButton: UIButton!

@IBOutlet weak var resultViewBottomConstraint: NSLayoutConstraint!
@IBOutlet weak var resultViewTopConstraint: NSLayoutConstraint!

var currentQuestion:Question?

var  model:QuizModel?
var questions = [Question]()

var numberCorrect = 0

override func viewDidLoad() {
    super.viewDidLoad()
    model = QuizModel()
    model?.getQuestions()
}

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nil, bundle: nil)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}
func setAll(questionsReturned:[Question]) {

    self.loadViewIfNeeded()
    // Do any additional setup after loading the view, typically from a nib.

    // Hide feedback screen
    dimView.alpha = 0

    // Call get questions
    questions = questionsReturned

    // Check if there are questions
    if questions.count > 0 {

        currentQuestion = questions[0]

        // Load state
        loadState()

        // Display the current question
        displayCurrentQuestion()
    }

print("Called!")

}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func displayCurrentQuestion() {

    if let actualCurrentQuestion = currentQuestion {

        // Set question label to alpha 0
        questionLabel.alpha = 0

        // Set the question label
        questionLabel.text = actualCurrentQuestion.questionText

        UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut, animations: { 

                self.questionLabel.alpha = 1

            }, completion: nil)

        // Create the answer buttons and place them into the scrollview
        createAnswerButtons()

        // Save state
        saveState()
    }

}

im getting error while setting alpha of dimView and questionLabel. I don't know why because they are connected by the storyboard

PS. When I set breakpoint on this dimView.alpha = 0 and type po dimview in console it says that dimView is nil

Edit: I have some informations that can be useful. When I set alpha of DimView and questionLabel before I call model?.getQuestions() it works and when I set breakpoint there and type po dimView! into console it returns some values. enter image description here

And questionsLabel have something too. enter image description here

But when code goes into model?.getQuestions(), and then I type po dimView! it returns nil. enter image description here

Jacob233
  • 312
  • 2
  • 4
  • 14

2 Answers2

2

setAll(questionsReturned:[Question]) is getting called before viewDidLoad() is called. The @IBOutlets aren't connected until just before viewDidLoad() is called.

class ViewController: UIViewController {
    @IBOutlet weak var myLabel: UILabel!

    var myText: String = ""

    func viewDidLoad() {
        super.viewDidLoad()
        myLabel.text = myText
    }

    set(myText: String) {
        self.myText = myText
    }
}

Do it like the above...

-- Edit --

I notice in your screenshots that displayCurrentQuestion is being called on a different view controller object than the view controller that was loaded in the screenshot where viewDidLoad is called. It could be that you are creating a second view controller somewhere?

Do this... Put break points at the beginning of your displayCurrentQuestion and viewDidLoad methods. Then run your app. You will find that either displayCurrentQuestion is getting called before viewDidLoad is, or it is being called on a different object that viewDidLoad was called on (you can tell it's a different object by the hex value of the self variable.)

Daniel T.
  • 32,821
  • 6
  • 50
  • 72
  • How can I fix this? – Jacob233 Mar 09 '17 at 21:21
  • Instead of trying to change the state of IBOutlets inside `setAll`, create some properties with the information (this is called a Model) and then set the IBOutlets in `viewDidLoad` from the model. – Daniel T. Mar 09 '17 at 21:23
  • Im trying to understand what I have to do, you mean that I have to create another file/function where I will set this values? Sorry, I'm new to swift and programming – Jacob233 Mar 09 '17 at 21:26
  • I added code to my answer – Daniel T. Mar 09 '17 at 21:29
  • is it only one way to do that? I have a lot staff like that – Jacob233 Mar 09 '17 at 21:38
  • oh I think I got it, I have to do that only with properties in 'setAll()' function ? – Jacob233 Mar 09 '17 at 21:40
  • Every view controller should have a property that represents it's model. Some outside source sets the view controller's model, and then in the viewDidLoad, the view controller sets up the views based on the state of the model. The only other option is to not call your `setAll` method until after viewDidLoad starts. – Daniel T. Mar 09 '17 at 21:40
  • But you mean `func set(myText: String) { self.myText = myText } ` ? – Jacob233 Mar 09 '17 at 21:57
  • I have edited my post and added some informations from debugging that can be useful – Jacob233 Mar 10 '17 at 17:05
  • I edited my answer. The answer is essentially the same but it might be that you have two view controllers in existence... – Daniel T. Mar 17 '17 at 15:57
0

It is also good to check your IBOutlet connections with your viewcontroller in storyboard, there might be wrong connections

abdullahselek
  • 7,893
  • 3
  • 50
  • 40