Question

In my case I'm using a UITextField as the accessory that I don't need to show all the time. I've confirmed the change happens after the orientation notification events fire. I guess a hack would be to resize the accessory to zero height, but I'm reticent to do this.

Wondering if anyone has encountered this and found a solution?

Have entered a bug report and provided a sample project. For those with higher privileges, it is searchable on bugreport.apple.com as ID 16771757. I have also copied it to a Dropbox account accessible as https://www.dropbox.com/s/o28vo04ig3yhgz6/ID16771757.zip.

Thank you for reading.

Was it helpful?

Solution

iOS calls such methods for input accessory view instance:

  1. [inputAccessoryView setAlpha:1]; when owner of accessory view becomes first responder (internal method call -[UIPeripheralHost(UIKitInternal) executeTransition:]);
  2. [inputAccessoryView setHidden:NO]; when interface rotation finished (internal method call -[UIPeripheralHost finishRotationOfKeyboard:]);

That's why your input accessory view becomes visible after interface rotation event.

Solution depends on behaviour that you expect:
Let's imagine that input accessory view height = 44 ->
Now you hide input accessory view and set owner as first responder:
If you expect inputAccessoryView.frame.size.height equals 0 then solution for hiding input accessory view is set it to nil: inputAccessoryView = nil;

If you expect inputAccessoryView.frame.size.height equals 44 then solution for hiding input accessory view is override setHidden: method for it:

- (void)setHidden:(BOOL)hidden {
    [super setHidden:self.customIsHiddenFlag];
}  

where customIsHiddenFlag property that you need use for implementing logic of showing/hiding accessory view;

or override setAlpha: method:

- (void)setAlpha:(CGFloat)alpha {
    [super setAlpha:(self.customIsHiddenFlag ? 0 : 1)];
}

These solutions work for iOS 7.

For iOS 6 you could use your base solution inputAccessoryView.hidden = YES and it works because iOS doesn't call setHidden:NO automatically when interface rotation is fired.

It seems that you are right and it's a bug cause of different behaviour on iOS6 and iOS7. If Apple wants to show input accessory view forcedly then they should call setHidden:NO not only after interface rotation but also when owner becomes first responder.

OTHER TIPS

From Apple's documentation on inputAccessoryView:

Subclasses that want to attach custom controls to either a system-supplied input view (such as the keyboard) or a custom input view (one you provide in the inputView property) should redeclare this property as readwrite and use it to manage their custom accessory view. [emphasis mine]

So the correct way to hide the accessory view would be redeclaring the property as readwrite:

@property (nonatomic, readwrite) UIView *inputAccessoryView;

removing the accessory view from superview and setting the property to nil when appropriate:

- (IBAction)hideAccessoryView:(UIButton *)sender
{
    [self.inputAccessoryView removeFromSuperview];
    self.inputAccessoryView = nil;
}

This is correct with regard to the docs but if you look at the view hierarchy, there's a UIPeripheralHostView (UIKit private class) that does not change its size. This most likely means that throwing out the accessory view will not be reflected by keyboard size — it'll stay the same. Keep this in mind if you plan to calculate any offsets to adjust to on-screen keyboard.

That said, the best way for you to move forward might be using a completely transparent view as the accessory view and have your custom view (UITextField in this case) as a subview. That way you will get both complete control over your custom view and consistent behaviour of your app on current and future versions of iOS.

Edit:

Here's a screenshot showing a slightly modified version of your bug report app with UIPeripheralHostView highlighted:

Reveal screenshot

You can see how size of the view stays the same after the accessory view has been removed.

When you add an accessory view, you "pass" it to the system for layout. It is more than likely, when Apple performs layout on the keyboard view, it also layouts the accessory view and sets it to visible. Setting the accessory as hidden can also have other side effects, such as the keyboard height being incorrectly calculated, thus causing incorrect inset calculation.

From my experience, it is best to remove the accessory and add it again when necessary. Resizing the accessory view will cause other issues related to keyboard size. If you want to hide and show quickly, subclass the view that includes the accessory view, and implement internally the setting and removing of accessory view.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top