How to access IBOutlet values that are in my controller - from another class in a separate swift file?

I have a storyboard connected to a view controller. I have created the necessary IBOutlets in the view controller to access items off the storyboard, that all works fine.

I created a separate swift file with a new class and some methods, in order to do some processing based on information from the storyboard.
To access information from my controller I created a pointer(?) back to the controller, that looks like this:
let View1:ViewController = ViewController()

This seems to allow me to access information that comes from the view controller, EXCEPT the values for my IBOutlets.

I am getting an error saying → that while trying to unwrap an optional a value of nil was found.
Could somebody explain what is going on, what I’m doing wrong and how to do it correctly?

It seems to be “partially” working, I just don’t know how to access the IBOutlet values from a class in a separate swift file.

Thank you - Ed Campbell

ViewController() is not a reference to the view controller that you have hooked up to outlets in Interface Builder. It’s actually an entirely new instance of ViewController, devoid of any of the setup that you’re currently expecting!

Are you sure you really need reference to the entire ViewController? I think that you may be better off sending over the specific data that you need. The umbrella term for this is dependency injection. I’m sorry that I don’t currently know of a beginner’s article on it, but this one is specifically about UIViewControllers. I use inject-style methods, myself.

https://www.natashatherobot.com/update-view-controller-data-injection-with-storyboards-and-segues-in-swift/

Thanks for your answer.
I do understand now that I was just giving myself access to the viewController methods, not necessarily to the information available thru the IBOutlets that are in the viewController.

I looked at the link you gave me regarding dependency injection and also a couple of others, however as a semi-new swift user I must admit I am still fairly confused by dependency injection.

If I give a simple example of what I am trying to do perhaps you could show me what I need to do, or perhaps someone else who reads this reply can.
If not I understand. I’m just hoping what I need is not too difficult and once I see how do do it perhaps the lightbulb will go on. I think my needs are pretty simple so I’m hoping the solution will be simple as well.


Starting my sample:


  • I have a count down Label on my storyboard.

  • I created an IBOutlet for that countdown label in the view controller so I could update it.
    @IBOutlet weak var countDownLabel: UILabel

  • I created a class in a separate swift file that will do some processing and if the counter changes then I need the view controller to update the Label (countDownLabel) on my storyboard.

  • How can I access the countDownLabel in this class and update it so that the storyboard reflects the change?


That is my example situation.


If I can see how to do that one thing I’m hoping I can figure out how to access other items from the storyboard so they can be updated from my new class, without my having to do the processing in the view controller.

This whole situation came about because I was reading that I should try to keep as much processing as possible out of my view controller, so I’m attempting to do that.

Thank you again - Ed

“Keep[ing] as much processing as possible out of my view controller” isn’t providing concrete enough information. You can always remove all direct code from a view controller, but that doesn’t mean that it’s really removed from the view controller’s control. You must not make spaghetti just to get code out of a file. Is there a pattern you’re trying to adhere to?

The places I think it might make sense to update the label, are in the view controller with an outlet-reference to it, or in a class that you assign to the label itself. Possibly, you could dependency inject a reference to the label to this other class you’re talking about, but you wouldn’t want to do that directly, but only via a closure.

How can you inject dependencies, which is to say, pass what you need? Usually prepareForSegue works.

I think this method works. I hope I have understood your problem and my answer makes sense.

In your class that does the processing have
var controller = ViewController?

Then when your processing is completing call the function in the view controller:
controller.updateLabel(value)

In your View Controller
Have a function that updates the label
func updateLabel {
update the label
}

When you create the processing class set the variable linking them together
let class = ProcessingClass()
class.controller = self