Preamble
So I have an application featuring a chat section, and I'm synchronizing the animation of the keyboard hiding and showing with the rise and fall of the chat input.
Here's the code I'm using:
SHOW:
- (void) keyboardWillShow:(NSNotification *)note {
    NSDictionary *keyboardAnimationDetail = [note userInfo];
    UIViewAnimationCurve animationCurve = [keyboardAnimationDetail[UIKeyboardAnimationCurveUserInfoKey] integerValue];
    CGFloat duration = [keyboardAnimationDetail[UIKeyboardAnimationDurationUserInfoKey] floatValue];
    NSValue* keyboardFrameBegin = [keyboardAnimationDetail valueForKey:UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
    // working for hardware keyboard
    //UIViewAnimationOptions options = (UIViewAnimationOptions)animationCurve;
    // working for virtual keyboard
    UIViewAnimationOptions options = (animationCurve << 16);
    [UIView animateWithDuration:duration delay:0.0 options:options animations:^{
        textView.frame = CGRectMake(0, self.view.bounds.size.height - keyboardFrameBeginRect.size.height, self.view.bounds.size.width, -40);
    } completion:nil];
}
HIDE:
- (void) keyboardWillHide:(NSNotification *)note {
    NSDictionary *keyboardAnimationDetail = [note userInfo];
    UIViewAnimationCurve animationCurve = [keyboardAnimationDetail[UIKeyboardAnimationCurveUserInfoKey] integerValue];
    CGFloat duration = [keyboardAnimationDetail[UIKeyboardAnimationDurationUserInfoKey] floatValue];
    // hardware keyboard
    //UIViewAnimationOptions options = (UIViewAnimationOptions)animationCurve;
    // virtual keyboard
    UIViewAnimationOptions options = (animationCurve << 16);
    [UIView animateWithDuration:duration delay:0.0 options:options animations:^{
        textView.frame = CGRectMake(0, self.view.bounds.size.height, self.view.bounds.size.width, -40);
    } completion:nil];
}
This works great with the virtual keyboard, but if keyboardWillShow: or keyboardWillHide: is called as a result of disconnecting or connecting a hardware keyboard, the animation lags. I can fix this by changing the UIViewAnimationOptions
Replace:
// Works with virtual keyboard
UIViewAnimationOptions options = (animationCurve << 16);
With:
// working for firstResponder keyboard
UIViewAnimationOptions options = (UIViewAnimationOptions)animationCurve;
But with this, now the virtualKeyboard animation lags
I realize that hardware keyboard animations aren't very common and it's perhaps not the most important issue, but I like everything to just work!
Examples
VirtualKeyboard w/ (animationCurve << 16) -- WORKING

VirtualKeyboard w/ (UIViewAnimationOptions)animationCurve -- BROKEN

HardwareKeyboard w/ (animationCurve << 16) -- BROKEN

HardwareKeyboard w/ (UIViewAnimationOptions)animationCurve -- WORKING

Notes
To simulate hardware keyboard in simulator cmd + shft + k
Yes, this is replicable on real device.
In case you want it, here's the rest of my code, just for replication purposes
ADD TEXT VIEW
textView = [UITextView new];
textView.layer.borderWidth = 10;
textView.layer.borderColor = [UIColor blackColor].CGColor;
textView.frame = CGRectMake(0, self.view.bounds.size.height, self.view.bounds.size.width, -40);
[self.view addSubview:textView];
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc]init];
[tap addTarget:self action:@selector(handleTap:)];
[self.view addGestureRecognizer:tap];
// OBSERVE KEYBOARD
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide:)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
HANDLE TAP:
- (void) handleTap:(UITapGestureRecognizer *)tap {
    NSLog(@"tapped");
    [textView resignFirstResponder];
}
The Question:
What is going on here, and is there a good way to get consistent animation regardless of virtual / hardware keyboard?
I realize this is long, thank you for reading!