UITextField Text Invisible Until Editing

2019-08-09 19:27发布

问题:

I've implemented a subclass of UITextField that has padding as follows:

methods taken from here

- (CGRect)textRectForBounds:(CGRect)bounds {
    return CGRectInset(bounds, 10, 10);
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    return CGRectInset(bounds, 10, 10);
}

With a combination of the above, setting the textField as the firstResponder in viewWillAppear:, and having an initial starting value in the field, I've run into an issue where the text is invisible until the field is edited, and then is fine after that:

When this occurs, I also see the following message in the console:

-[<CALayer: 0x15f000da0> display]: Ignoring bogus layer size (179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000, 20.000000), contentsScale 3.000000, backing store size (inf, 60.000000)

I thought perhaps the bounds value was out of whack, and that was what was causing both the visual bug and error, but when I log the bounds I get a bunch of values that appear to be valid, such as: {{0, 0}, {345, 40}}

Commenting out those two methods above, to basically be a normal UITextField, seems to fix the issue. I've tried adding calls to super in each of those methods, just in case that were to help, to no avail. Any ideas?

Update - Moving the call to becomeFirstResponder to viewDidAppear seems to also fix the issue, but that pretty much kills the flow in what is basically a wizard, and thus the previous screen also has the keyboard on screen, so I'd like to avoid the keyboard dismissing and reappearing on every screen.

回答1:

Thanks to @matt, I discovered that the issue is caused because I'm calling becomeFirstResponder on the textfield in viewWillAppear. Although this has worked for me with normal textfields and textviews for years without issue, it appears this is finally an instance where an issue arose.

According to the UIResponder docs for becomeFirstResponder:

You may call this method to make a responder object such as a view the first responder. However, you should only call it on that view if it is part of a view hierarchy. If the view’s window property holds a UIWindow object, it has been installed in a view hierarchy; if it returns nil, the view is detached from any hierarchy.

This was validated by printing [[self.textfield superview] window] in the debugger, and in viewWillAppear the window is nil, whereas it isn't in viewDidAppear. Learn something new every day.