didSet property observer to call a method question

Hello,

can anyone explain why this didSet is not working?

error message is saying that “Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value”

but if I add viewUpdate() method in viewDidLoad() then it works fine

import Foundation
import UIKit

class DefinitionViewController: UIViewController {

var vocabWord: VocabularyWord? {
    didSet {
        updateViews()
    }
}

// didSet to call updateViews() method.

@IBOutlet weak var wordLabel: UILabel!
@IBOutlet weak var wordDefinition: UITextView!


override func viewDidLoad() {
    super.viewDidLoad()
    
}

func updateViews() {
    if let unwrappedVocabword = vocabWord {
        wordLabel.text = unwrappedVocabword.word
        wordDefinition.text = unwrappedVocabword.definition
    } else {
        print("no input")
    }
}

}

Thank you for your help!!

Dongwoo

Your implicitly unwrapped outlets don’t have values when you get that crash. One easy way to solve the problem is with https://developer.apple.com/documentation/uikit/uiviewcontroller/1621446-loadviewifneeded

Thank you for your quick response!

I added loadViewIfNeeded() inside of didSet observer before calling updateViews() and it works but I am not sure why and how it fixed the issue.

how does this loadViewIfNeeded() work here?

is there something behind of willSet and didSet that I am having gaps? i have seen several examples of printing output with conditionals within willSet and didSet but I have not seen any on how to call a method inside of didSet property observer. Is loadViewIfNeeded() what we use to call a method inside?

class DefinitionViewController: UIViewController {

var vocabWord: VocabularyWord? {
didSet {
loadViewIfNeeded()
updateViews()
}
}

// didSet to call updateViews() method.

@IBOutlet weak var wordLabel: UILabel!
@IBOutlet weak var wordDefinition: UITextView!

override func viewDidLoad() {
super.viewDidLoad()

}

func updateViews() {
if let unwrappedVocabword = vocabWord {
wordLabel.text = unwrappedVocabword.word
wordDefinition.text = unwrappedVocabword.definition
} else {
print(“no input”)
}
}

}

Thank you!

Dongwoo

The problem occurs because you are setting vocabWord to some value, before you load the view controller and it’s view. The didSet method then tries to update the view before it is loaded.

You can guard against the exception in func updateViews() by adding this line at the beginning:

  guard isViewLoaded else { return }

If you have set a value for vocabWord before loading the view, it won’t get displayed by the didSet because of the guard statement. You can fix that by adding a call to viewDidLoad:

override func viewDidLoad() {
   super.viewDidLoad()
   updateViews()
}

With that done, you won’t need to use loadViewIfNeeded()

1 Like

Okay I appreciate the answer!!

This topic was automatically closed after 166 days. New replies are no longer allowed.