iOS IBOutlet is non-nil, somehow being scavenged to nil

64 views Asked by At

TL;DR: I have an IBOutlet (UILabel) that is properly connected in Storyboard. Accessing (unwrapping) it works fine in viewDidLoad() ... but a few seconds later its value is nil. A watchpoint says that the outlet changes right after a call to viewDidLayoutSubviews(), but... a print() call at the end of viewDidLayoutSubviews() shows it non-nil.

This is very similar to IBOutlet is nil but his solution (track value with didSet()) did not work. (There are many related posts but all had trivial solutions.)

What I have done:

  • Reconnected the outlet to the Label — from both sides
  • Deleted the Label and reconnected it
  • Cleaned the project
  • Deleted the DerivedData
  • Quit and restarted Xcode
  • Quit and restarted my Mac
  • Added a didSet() method to the outlet.
    • It triggers during viewDidLoad() and shows a non-nil value.
    • In viewDidLoad() I set its text value with no problem
    • It does not trigger before the nil-unwrapping crash
  • Added a watchpoint to the variable.
    • This does trigger before crash (right after viewDidLayoutSubviews() and shows the following:

screenshot of Xcode debugger

As mentioned before, at exit of the most recent method call before the watchpoint (viewDidLayoutSubviews()) the outlet is non-nil.

These crashes seem always to involve subviews of a particular superview. I added a watchpoint to the superview's outlet but it never triggers.

What could be inciting my code to let go of this weak reference?

1

There are 1 answers

0
Andrew Duncan On

TL;DR: I was clobbering the relevant views.

Well, the best way to find your own answer is to ask someone else. Thanks to @DonMag, I was preparing more traces, breakpoints, and screen shots. I noticed this method (added to fix another bug, of course):

screen shot showing me removingFromSuperview the very views that were nil

Of course, the two views that were becoming nil were subviews of centralOverlay. Ones I wanted to keep.

So I guess my answer was similar to that of IBOutlet is nil — pilot error — except the didSet() handler did not solve the mystery.