"Unexpectedly found nil while unwrapping an Optional value" with UIColor

Xcode 13.0 is driving me crazy at the moment...

I've got a couple of color sets (default sRGB with "Any Appearance" & "Dark") that are used in various UIViewControllers. Two of them I also use in a custom button class:

class SpecialBorderButton:UIButton {
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        if #available(iOS 13.0, *) {
            super.traitCollectionDidChange(previousTraitCollection)
             if (traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection)) {
                 layer.borderColor = UIColor(named: "ButtonBorderColor")!.cgColor
             }
        }
    }
}

What the code does: When the theme is changed while the app is running, usually the border of a button wouldn't change until you reload the ViewController. traitCollectionDidChange is called when the theme changes and this way the border color is set properly too.

The issue navigator has been throwing the same error for 3 different UIViewControllers since I installed Xcode 13:

Failed to render and update auto layout status for ViewController (.....): The agent crashed

The crash report in Library/Logs/DiagnosticReports says:

CoreSimulator 776.3 - Device: iPhone SE (1st generation) (...simulator code...) - Runtime: iOS 15.0 (19A339) - DeviceType: iPhone SE (1st generation) myApp/SpecialButton.swift:26: Fatal error: Unexpectedly found nil while unwrapping an Optional value

First of all, I don't even use the SE 1G/iOS 15 simulator but always the SE2/iOS13 one, also, I checked one of the buttons that use that class and pressed "Debug" next to "Designables Crashed" in the Attribute Inspector and it blames the same line:

layer.borderColor = UIColor(named: "ButtonBorderColor")!.cgColor

... with the same error:

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

The reason why I'm writing this question: The color exists! I checked the spelling multiple times and also copied the name but the errors are still there. I deleted derived data, cleaned the build folder and restarted Xcode and the mac multiple times but the error never fully vanish for all 3 ViewControllers. There aren't any wonky connections to that button either (as far as I've seen).

I use UIColor(named:....) with different colors in multiple other classes too (but without the custom class) and they're fine there, it's just this class that's affected, for whatever reason.

How do I fix this?

Replies

You unwrap something that may be nil:

UIColor(named: "ButtonBorderColor")

So, to avoid crash, replace by:

layer.borderColor = UIColor(named: "ButtonBorderColor")?.cgColor ?? UIColor.clear.cgColor // Or choose another default color

How did you define ButtonBorderColor ? It should be in Assets.

Read here how to create color in assets:

h t t p s : / / medium.com/developerinsider/xcode-pro-tips-how-to-use-asset-catalogs-to-support-named-colors-8959ab51fd84

Note: to be sure of the cause, add a print:

if (traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection)) {
       print("Color is",  UIColor(named: "ButtonBorderColor"))
       layer.borderColor = UIColor(named: "ButtonBorderColor")?.cgColor ?? UIColor.clear.cgColor
}
  • Thanks for you reply. I know what the error means but it shouldn't be thrown because the UIColor exists, that's the problem. I used the same code before I updated to Xcode 13 and everything was fine then. Yes, I did create the color in Assets, it's a regular color set, like the other 10+ I'm using in my app. All of these other color sets work fine, it's only this one in this specific function/class. I did already add a print similar to yours (something that checks for nil) but it was never printed to console, probably because I never changed the theme, even though the overall error still showed up. I also just tested your print and actively changed the color while my app was running in the SE2 simulator: Everything's fine, the color isn't nil and changes properly but the error's still there in the Issue Navigator. Currently I'm only getting the "The agent crashed" error for one of the 3 VCs, it seems to be pretty random.

  • Did you try to use this color elsewhere ? In a place where some color works, change to this color immediately after. Does it crash then ? What I don't understand: if print is not called, that means the crash is not there ? Or do I miss something ?

  • if print is not called, that means the crash is not there - that's the weird bit: The app doesn't crash. When I start it in the SE2 13.5 simulator, everything's working fine, the colors are set properly, including when I switch to the dark theme and the print is written to console with the proper color (not nil). But the whole time the error is listed in the Issue Navigator and there's also the small, red circle with the white x in the bar of the open files (in the part of Xcode that can display the storyboard or code). When I click on the error in the Issue Navigator, the storyboard opens with the affected ViewController selected. When I just did that, Xcode did some loading and all of the sudden the error didn't show up for VC3 anymore but instead VC1 (yesterday it listed up to 3 VCs). When I click on the error, it doesn't jump to the affected UI item though, I have to find that myself and there's also no red circle next to the UI item or the VC (as it usually would be if there's a storyboard error). In the Attributes Inspector of that UI item you can see this: https://i.imgur.com/ZZfhd35.png - Clicking on "Debug" opens an iPhone 13 Pro simulator (didn't notice that until now) and then the app crashes on it with EXC_BAD_INSTRUCTION for that line. The weirdness doesn't stop there: If I select the iPhone 13 Pro simulator manually and start the app, everything's fine, no crash and the colors are set properly, even with force unwrapping. No idea what's going on here.