random
random

Reputation: 8608

Reusing a UIView causes app to freeze

I'm not sure if this is a bug or if I'm actually doing something wrong.

    let spacerView = UIView(frame: CGRectMake(0,0,10,10))

    self.drugNameTextField.leftViewMode = .Always
    self.drugNameTextField.leftView = spacerView

    self.locationTextField.leftViewMode = .Always
    self.locationTextField.leftView = spacerView

Reusing spacerview here causes my app to never get past the splash screen. Simply freezes.

If I do this, app launches fine and makes it past the splash screen:

    let spacerView = UIView(frame: CGRectMake(0,0,10,10))

    self.drugNameTextField.leftViewMode = .Always
    self.drugNameTextField.leftView = spacerView

    self.locationTextField.leftViewMode = .Always
    //self.locationTextField.leftView = spacerView

Is reusing a UIView like this technically wrong? Or should I file a bug?


Just for thoroughness sake, I know you could do this:

    self.drugNameTextField.leftViewMode = .Always
    self.drugNameTextField.leftView     = UIView(frame: CGRectMake(0,0,10,10))

    self.locationTextField.leftViewMode = .Always
    self.locationTextField.leftView     = UIView(frame: CGRectMake(0,0,10,10))

Upvotes: 0

Views: 241

Answers (1)

rob mayoff
rob mayoff

Reputation: 385690

No, you can't use the same view in two places like that.

A view can have only one superview. During layout, drugNameTextField adds its leftView (spacerView) as a subview of itself. Then locationTextField adds its leftView as a subview of itself. Since that is also spacerView, spacerView first removes itself from its parent.

If you pause in the debugger, you'll see a stack trace similar to this:

#0  0x036bf6f1 in -[NSConcreteTextStorage string] ()
#1  0x0195b09f in -[UITextField _text] ()
#2  0x0195b55b in -[UITextField _hasContent] ()
#3  0x019580de in -[UITextField _layoutLabels] ()
#4  0x01958ccf in -[UITextField _layoutContent] ()
#5  0x01958e5e in -[UITextField layoutSubviews] ()
#6  0x00eeb1c2 in -[UIView(CALayerDelegate) layoutSublayersOfLayer:] ()
#7  0x00556059 in -[NSObject performSelector:withObject:] ()
#8  0x04e4392a in -[CALayer layoutSublayers] ()
#9  0x04e37194 in CA::Layer::layout_if_needed(CA::Transaction*) ()
#10 0x04e36ff8 in CA::Layer::layout_and_display_if_needed(CA::Transaction*) ()
#11 0x04e297b7 in CA::Context::commit_transaction(CA::Transaction*) ()
#12 0x04e5e107 in CA::Transaction::commit() ()
#13 0x04e5e9c8 in CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) ()
#14 0x0099b86e in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
#15 0x0099b7ce in __CFRunLoopDoObservers ()
#16 0x00990978 in CFRunLoopRunSpecific ()
#17 0x0099076b in CFRunLoopRunInMode ()
#18 0x00e18812 in -[UIApplication _run] ()
#19 0x00e1e299 in UIApplicationMain ()
#20 0x0006c8ea in main at /Users/mayoff/TestProjects/test/test/main.m:14
#21 0x03180a25 in start ()

If you put a breakpoint on -[UITextField layoutSubviews], you'll see that the system is calling it over and over. The two text fields are “fighting” over who gets to be the superview of spacerView. Each time one text field adds spacerView as a subview, it removes spacerView from the other text field's subviews, so the other text field gets flagged as needing layout again. The system never gets out of the layout phase.

Upvotes: 2

Related Questions