Swift下IQKeyboardManager在UIScrollView多UITextField切换时滚动偏移异常问题
问题根因
这个是iOS 14~iOS 15版本中UIScrollView内置的输入框偏移适配逻辑的系统Bug,原因是系统处理键盘弹出通知时,优先读取了上一次第一响应者输入框的位置缓存,没有同步更新为当前新激活的输入框坐标,导致滚动位置错误。
可行修复方案
方案1:手动控制滚动偏移(无感知适配,推荐)
禁用UIScrollView的自动偏移调整,自己监听键盘通知计算当前激活输入框的位置,手动设置滚动偏移:
- 首先关闭系统自动调整逻辑
// iOS 11及以上版本 if (@available(iOS 11.0, *)) { self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } else { self.automaticallyAdjustsScrollViewInsets = NO; } self.scrollView.adjustsScrollIndicatorInsets = NO;
- 监听键盘弹出通知,手动计算滚动位置
// 注册通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; // 实现键盘处理方法 - (void)handleKeyboardWillShow:(NSNotification *)noti { NSDictionary *info = noti.userInfo; CGRect keyboardEndFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue]; NSTimeInterval duration = [info[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; // 查找当前激活的输入框 UIView *currentResponder = [self findFirstResponderInView:self.scrollView]; if (!currentResponder) return; // 转换坐标到scrollView坐标系 CGRect responderFrame = [currentResponder convertRect:currentResponder.bounds toView:self.scrollView]; // 计算可视区域高度,输入框底部需要保留16px安全边距 CGFloat visibleHeight = CGRectGetHeight(self.scrollView.bounds) - CGRectGetHeight(keyboardEndFrame); CGFloat targetOffsetY = MAX(0, CGRectGetMaxY(responderFrame) - visibleHeight + 16); // 同步系统键盘动画设置滚动偏移 [UIView animateWithDuration:duration delay:0 options:[info[UIKeyboardAnimationCurveUserInfoKey] integerValue] animations:^{ self.scrollView.contentOffset = CGPointMake(0, targetOffsetY); } completion:nil]; } // 递归查找第一响应者 - (UIView *)findFirstResponderInView:(UIView *)parentView { if (parentView.isFirstResponder) return parentView; for (UIView *subView in parentView.subviews) { UIView *responder = [self findFirstResponderInView:subView]; if (responder) return responder; } return nil; }
如果使用Swift,语法对应转换即可,逻辑完全一致。
方案2:切换输入框时先收起键盘再弹出
如果不想写太多代码,可以在输入框的textFieldShouldBeginEditing代理方法中,先让当前已激活的输入框取消第一响应,等键盘完全收起后再让新的输入框激活,缺点是会有键盘收起再弹出的过渡动画,体验略逊于方案1。
补充说明
该Bug已经在iOS 16及以上版本被苹果官方修复,如果你的App最低兼容版本为iOS 16及以上,无需做额外适配处理。
内容的提问来源于stack exchange,提问作者Nawin Poolsawad
相关产品推荐
相关产品推荐

