1

I have a ViewController called : ViewController I have a AppDelegate called : AppDelegate

They are not made programmatically, they are are just as default when you create a new app in swift.

Imagine that in the ViewController I have:

class ViewController: UIViewController {

  var animal = "dog" 

}

For example, I want to print animal value when the app goes in the background. So in the AppDelegate i have:

func applicationDidEnterBackground(_ application: UIApplication) {

    var ViewController: ViewController!

    print("animal = \(myViewController.animal)")   

}

I am getting : fatal error: unexpectedly found nil while unwrapping an Optional value

How can I access that value from my AppDelegate ? PS: I tried the first 2 pages of google/StackOverflow

4
  • 1
    this line var ViewController: ViewController! must be var controller = ViewController() and then print("animal = \(controller.animal)") Commented Feb 20, 2017 at 17:19
  • @ReinierMelian No, that is wrong because it simply creates a new view controller and makes no reference to the existing controller. Commented Feb 20, 2017 at 17:27
  • 1
    Well @rmaddy I know that this is no the best approach, but I was trying to explain thinking in what he needs is print a static value in his ViewController Class Commented Feb 20, 2017 at 17:33
  • @ReinierMelian But it's very misleading. You make it seem like the solution is to create a new instance of the view controller. That's simply not true. Commented Feb 20, 2017 at 17:49

3 Answers 3

4

You need get the rootViewController

func applicationDidEnterBackground(_ application: UIApplication) {

    let viewController = self.window?.rootViewController as? ViewController
    print(viewController?.animal)

}
Sign up to request clarification or add additional context in comments.

7 Comments

You really should avoid all of these ! (crash operator).
Why did you only remove one of the ! and not both?
@rmaddy so casting an already initialized rootViewController to ViewController is different from just initializing to ViewController?
@Honey Of course this answer assumes that the app's root controller is the desired view controller. This code may need to be adjusted if the view controller in question is further down in the view hierarchy.
@Honey No, not really. What I stated is exactly what I meant. I have no idea if the desired view controller is the root view controller. That was proposed by this answer, not me.
|
2

You can get the rootViewController in the AppDelegate but you can not make sure if at the time of going to the background that was the visible view controller and you might end up on another ViewController

The best way to implement what you need is to add the function in your ViewController and assign an observer to UIApplicationDidEnterBackground notification

and when the controller is de-initialized you need to remove the observer

Something like

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, 
    selector: #selector(applicationDidEnterBackground), 
    name: NSNotification.Name.UIApplicationDidEnterBackground, 
    object: nil)    
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

func applicationDidEnterBackground() {
    //do something here
    print("animal: \(animal)")
}

3 Comments

This is probably the best approach for what the OP wants to do. However, a good answer will first explain what was wrong with the code in the question, and then offer an explanation of how to fix it. Then a great answer would offer this better, alternate solution after that.
And using viewWillAppear/Disappear may not be the best choice for adding/removing the observer. If this view controller has pushed or presented another view controller, then this code won't display the message when the app goes into the background. That may or may not be desired behavior.
@rmaddy thank you for your feedback I edited my answer
0

ALL optionals start from nil —unless you initialize them or set their default to be something else. Now, ask yourself where did I initialize my ViewController instance? Well you didn't!

var ViewController: ViewController! 

the line above ONLY means ViewController is of type ViewController, though it's also unwrapped (still not initialized though) from the beginning.

var ViewController = ViewController()

now this line means ViewController is initialized with a ViewController initializer. see the =? See the (). () is like do/initialize this.

So what the error is telling you is, you are messaging it, but still it's nil. If you initialize it, then it you can access its properties.

Having that said, this won't visually present the newly instantiated viewController. To do such you would have to do something like:

let vc = ViewController()
self.window?.rootViewController = vc

But that's a bad idea as rmaddy has mentioned in the comments. The alternative is to simply cast the existing rootViewController to ViewController as.

let viewController = self.window?.rootViewController as? ViewController

remember to cast you must use as? (safe casting) or as! (force casting)

5 Comments

But the OP wants to reference the existing view controller, not create a new instance.
Why does your update mention code to change the root view controller? The OP wants to display an existing value of an existing view controller. Suggesting that one solution is to create a new view controller and to make it the app's root view controller is way off the mark.
@rmaddy I think that the OP (having 120 reps) isn't much aware of this approach and it's just something to consider/learn
But how is the suggestion of replacing the existing root view controller with a new one each time the app enters the background the proper solution to display a property of some existing view controller in the app?
@rmaddy I see your point, it's a terrible one. :D. Thank you for putting all the comments and explaining it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.