Swift: UIImageView - Unexpectedly found nil while unwrapping an Optional value - swift

class DisplayImageVC: BasePageView { //BasePageView inherits from UIViewController
#IBOutlet weak var displayImage: UIImageView!
override func viewDidLoad() {
self.displayImage.backgroundColor = UIColor.yellowColor()
}
....
in another class I try this and get a fatal error:
var displayImageView = self._pageContent[1] as DisplayImageVC
displayImageView.displayImage.image = UIImage(named: ("displayChecklane"))
Log:
fatal error: unexpectedly found nil while unwrapping an Optional value
Images.xcassets

var displayImageView = self._pageContent[1] as DisplayImageVC
displayImageView.displayImage.image = UIImage(named: ("displayChecklane"))
You are crashing on the second line. You know this is because something is nil, but you do not know what is nil here. You are assuming it is the image. That is a false assumption; if it were correct, there would be no crash, as you are not force-unwrapping it, and it is legal to assign nil to an image view's image.
Instead, consider this: maybe displayImageView.displayImage is nil. That is, what is nil is the UIImageView you are trying to assign to. This would make sense since this is an outlet. If the DisplayImageVC's view has not loaded, its outlets have not been filled - they are still nil.
How you solve this depends on what you want to do. Personally I think your approach is bogus from the start; you have no business setting another view controller's outlet or a property of its outlet, or any aspect of its interface. You should have an image property in DisplayImageVC, and here, you should be setting that property; that way, when the view controller shows its view, it can configure its own interface.

Related

Fatal error: Unexpectedly found nil while changing Image and Label

I am trying to change a picture and a label programmatically.
Here's the current code setup:
#IBOutlet weak var image: UIImageView!
#IBOutlet weak var label: UILabel!
override func viewDidLoad(){
super.viewDidLoad()
setlabel()
setImage()
}
func setImage(){
self.image.image = UIImage(named: name)
}
func setlabel(){
self.label.text = string
}
But unfortunately, I'm receiving nil for both UI elements, the label and the image. I've doublechecked the connection between my storyboard and the variables- they are set correctly, imho. They are available, since I am calling them outside the viewDidLoad function.
Anyone any suggestion?
Regards
I found the solution. I had 2 views- let's call them A and B.
A contained a button- and the button had 2 functions: Change the view and set the labels/images. Those functions were defined in the Controller of view A.
Since I wanted to change the labels and images of view B, I got the exception.
I had to include another Controller and transfer the functions for setting the images and labels to Controller B. Voila, I could change the images and labels.
Summarized: I had the right connections and the right functions, but in the wrong place.
Thank you all!

#IBInspectable fatal error: unexpectedly found nil while unwrapping an Optional value

I got fatal error: unexpectedly found nil while unwrapping an Optional value when running my app it hangs for the following code
This is happening because the Inspectable is triggering your hasBottomLine property to be set, and therefore the didSet property observer to be called before your main view is loaded.
I'm going to guess that your lineHeightConstraint is probably defined as an implicitly unwrapped optional, something like:
#IBOutlet weak var lineHeightConstraint: NSLayoutConstraint!
You'll have to unwrap the optional before using it, for example:
lineHeightConstraint?.constant = hasBottomLine ? 3 : 0
There may be a chance that you still need to set this constraint after the view is loaded, so you might want to check if the optional contains nil, if so set a flag, and perform this line later in your viewDidLoad method. (or perhaps you can just call it regardless in your viewDidLoad)
Updated answer, with extra info that this code is in a subclassed UIView rather than UIViewController.
Rather than updating the constraint constant in your viewDidLoad method you could do so in the UIView's layoutSubviews method. For example:
override func layoutSubviews() {
super.layoutSubviews()
lineHeightConstraint?.constant = hasBottomLine ? 3 : 0
}

IBOutlet is nil

I have created a standard outlet for a view that will hold different information based on the button selected on the previous screen.
#IBOutlet weak var labelView: UIView!
It shows it is connected in both the story board view and on the code itself, however, every time I get to any reference to the labelView such as:
if detail.description == "About"
{
labelView.backgroundColor = UIColor.red
}
Then the app crashes out with:
fatal error: unexpectedly found nil while unwrapping an Optional value
I have tried everything I can think of or read on the internet:
Removed and replaced the connection
Deleted the derived data folder like one post suggested
Created a reference to self.view to force it to load
Moved it to viewDidAppear
Moved it to viewWillAppear
Moved it to viewDidLoad (which is where it is currently being
called)
I am sure at this point that the answer is rather simple and I am just completely missing it.
To see where the outlet is being set to nil, try this:
#IBOutlet weak var labelView: UIView? {
didSet {
print("labelView: \(labelView)")
}
}
You should see it set to an initial value when the view is loaded. If it then gets set to nil, put a breakpoint on the print and your should be able to see from the backtrace where it's happening.
Views are lazy initialized. In case you are calling the affected line of code before viewDidLoad() in the views life cycle, try to access viewin advance:
if detail.description == "About" {
_ = self.view
labelView.backgroundColor = UIColor.red
}

Swift - UIView.transitionFromView -

What happens to your “fromView” after you use UIView.transitionFromView? How do you get it back? (re-initialize it?).
Here’s a simple example I made and get “fatal error: unexpectedly found nil while unwrapping an Optional value” when I try to get back to the “fromView” or reference a label on it, etc.
Let’s say I’ve set these views in my storyboard - I added a subview to the root called “cardView” and then 2 views under cardView called “backView” and “frontView"
Linked these up to the view controller and linked the Flip button to an action that looks like this (along with the variables):
#IBOutlet weak var backView: UIView!
#IBOutlet weak var frontView: UIView!
#IBOutlet var cardView: UIView!
var front = true
#IBAction func flipIt(sender: AnyObject) {
if front {
UIView.transitionFromView(self.frontView, toView: self.backView, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: nil)
} else {
UIView.transitionFromView(self.backView, toView: self.frontView, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromLeft, completion: nil)
}
front = !front
}
So when I run this - the first tap of the “Flip” button does fine, it flips over to the backView, but then when I tap it again I get “fatal error: unexpectedly found nil while unwrapping an Optional value” on the 2nd transitionFromView line (the one under “else”).
Obviously there’s some effect of transitionFromView that I don’t understand. I've tried a lot of different things, including a tutorial that uses this transition and was able to get it working but it doesn’t use the storyboard so I’m not sure how to apply how that tut does it to my storyboard views, apparently...
thanks for any help.
You've declared your view properties as weak, so they're getting released as soon as it appears they're no longer needed. Just change them to strong (by removing "weak") and you should be golden:
#IBOutlet var backView: UIView!
#IBOutlet var frontView: UIView!

Set Image of UIImageView

I currently have a UITableView that holds a list of events. Each event has a button where the user can press it to get access to a larger view of a photo associated with the event. I have the UIButton connected and set up but I'm having a hard time setting the image in the new window. Here is my function:
func largeMap(sender: UIButton!) {
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let manager = NSFileManager.defaultManager()
self.performSegueWithIdentifier("largeMapView", sender: self)
println(sender.tag.description)
println(documentsPath+"/Flight"+(sender.tag.description)+"/Map.png")
if let image = UIImage(data: manager.contentsAtPath(documentsPath+"/Flight"+(sender.tag.description)+"/Map.png")!) {
largeMapView.image = image
}
}
When I run the app, it crashes at largeMapView.image = image and gives me "fatal error: unexpectedly found nil while unwrapping an Optional value". I've checked and the path for the image is correct and it is accessing the image but it's not able to set it to the UIImageView. I have the UIImageView outlet set at the top of the class. Why is this happening? I've set UIImageView's in this manner before but it just won't work now.
Basically the problem is that you are using exclamation marks. Exclamation marks are never safe! They can be a "bad smell", a danger signal - and in your code, that's just what they are.
(1)
I have the UIImageView outlet set at the top of the class.
But you do not show how it is set. You do not show what largeMapView is or how it is declared. The declaration might look like this:
#IBOutlet var largeMapView : UIImageView!
If so, that is bad - that is an implicitly unwrapped optional, which means it might be nil. This could be the source of your problem. By using a conditionally unwrapped optional you are covering up the problem - until you try to set into nil, and then you crash. If it is never being set properly, that's the reason for the crash.
(2)
Along the same same lines, the rest of your code, too, should not force-unwrap Optionals (using ! postfix operator) unless you know for certain that they can never be nil. Rewrite like this so that every Optional is unwrapped conditionally and safely:
if let d = manager.contentsAtPath(documentsPath+"/Flight"+(sender.tag.description)+"/Map.png") {
if let image = UIImage(data: d) {
largeMapView.image = image
}
}
This way, if contentsAtPath fails or UIImage(data:) fails, nothing will happen - you won't set your image - but at least you won't crash. And you can use stepping in the debugger to figure out where you are failing. - But even this will not save you if the problem is that largeMapView is a nil implicitly unwrapped Optional.