End-Frame in UIKeyboardWillChangeFrameNotification / UIKeyboardDidChangeFrameNotification is wrong for thirdparty keyboards

Originator:raise.rescue
Number:rdar://25032907 Date Originated:08-Mar-2016 03:12 PM
Status:Open Resolved:
Product:iOS SDK Product Version:iOS 9.3b6
Classification:UI/Usability Reproducible:Always
 
Summary:
We try to position a view on top / just under of the keyboard by using the UIKeyboardWillChangeFrameNotification and UIKeyboardDidChangeFrameNotification-notifications (we can not do that with an inputAccessoryView because of 25032665). Let aside that most of the notifications are garbage itself (totally wrong endFrames or irritating UIKeyboardBoundsUserInfoKey), their frequency is absurd (12 notifications when the iPad gets rotated - really?) and their patterns (docking the keyboard produces willChangeFrame, didChangeFrame, willShow, willChangeFrame, willShow, didChangeFrame, didShow, didChangeFrame, didShow), with the iOS-keyboards there is at least one notification that contains the right informations and we adapted our code to the patterns in a way so that we can pick out the correct notification.
Though, when a thirdparty-keyboard is being used, there is no notification that contains the right endFrame when the keyboard is undocked and being shown. So we are not able to show the view above the keyboard.

Steps to Reproduce:
1. Open the attached project
2. Execute it on an iPad
3. Install a thirdparty-keyboard-app - tested with “Fleksy” and “SwiftKey”
4. Tap into the textview to show the virtual keyboard - the orange view should move together with the keyboard
5. Choose an iOS-keyboard to undock it
6. Choose now the thirdparty-keyboard
7. Hide the keyboard
8. Tap again into the textview to show the virtual keyboard
9. The orange view is now hidden by the keyboard instead of being on top

If you struggle to reproduce it, the attached zip also contains a video demonstrating it.

Expected Results:
iOS should send one UIKeyboardWillChangeFrameNotification with the correct endFrame and one UIKeyboardDidChangeFrameNotification with the correct endFrame.

Actual Results:
It sends two willChangeFrame and two didChangeFrame-notifications, all with the wrong endFrames.

Regression:
-

Notes:
-

Comments

Our workaround-code

CGRect __block endFrame = [transitionInformation[UIKeyboardFrameEndUserInfoKey] CGRectValue];

WORKAROUND_OF_IOS_BUG(25032907)
// When a custom keyboard is being used, the keyboard-frame reported in the notifications are just wrong.
// This code tries to find the keyboard-view by traversing the windows and views.
// To find the view, we use the class-names of private-API which may change and break this mechanism.
// The worst case that can happen when this mechanism breaks is, that the keyboard-frame is not correctly detected.
if([notification.name isEqualToString:UIKeyboardDidChangeFrameNotification]) {
    for(UIWindow *window in [UIApplication sharedApplication].windows) {
        if([NSStringFromClass([window class]) isEqualToString:@"UIRemoteKeyboardWindow"]) {
            [window sip_callBlockRecursively:^(UIView *view) {
                if([NSStringFromClass([view class]) isEqualToString:@"UIInputSetHostView"]) {
                    XLog(@"take an other frame (%@ vs %@)", NSStringFromCGRect(endFrame), NSStringFromCGRect(view.frame));
                    endFrame = view.frame;
                }
            }];
            break;
        }
    }
}
By raise.rescue at March 8, 2016, 2:22 p.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!