1

当键盘显示并覆盖它时,我试图滚动到 UITextView 中的插入符号。不幸的是,它只有在我不为它制作动画时才有效,尽管 Apple 在 Notes 应用程序中做了同样的事情。我正在使用Apple 文档中解释的相同方法。

这是代码。它位于一个孤立的项目中,可以在没有任何其他干扰的情况下对其进行测试。只有一个添加了 UITextView 的视图控制器。我正在模拟器和设备上的 iOS 7 上对此进行测试。

- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedKeyboardDidShowNotification:) name:UIKeyboardDidShowNotification object:nil];
}

- (void)receivedKeyboardDidShowNotification:(NSNotification *)notification {
    CGRect keyboardBounds = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
    CGFloat keyboardDistanceFromBottomOfScreen = screenHeight - CGRectGetMinY(keyboardBounds);
    UITextView *textView = self.textView;
    UIEdgeInsets contentInset = textView.contentInset;
    contentInset.bottom += keyboardDistanceFromBottomOfScreen;
    textView.contentInset = contentInset;
    textView.scrollIndicatorInsets = contentInset;

    CGRect caretRect = [textView caretRectForPosition:textView.selectedTextRange.end];
    [textView scrollRectToVisible:caretRect animated:YES];
}

如果我将animated最后一行中的参数设置为NO,则效果很好(当然,没有动画,这是我不想要的)。通过YES会产生奇怪的行为。大多数情况下,视图不会滚动或仅滚动几个像素,但有时它会产生我想要的行为,因此结果是随机的。

我试图计算插入符号的偏移量并使用setContentOffset:animated:方法而不是scrollRectToVisible:animated:,但结果是一样的。如果animated是,它会起作用NO。有了YES它会产生同样奇怪的结果。

更奇怪的是,在第二个解决方案中,该行上的断点被击中了两次,尽管通知只传递了一次。上一行或我在其后添加的一行上的断点(什么都不做,只是一个用于测试的日志语句)只被击中一次。为了增加更多的陌生感,在三行上放置日志断点会产生以下结果:

Line before
Buggy line
Line after
Buggy line

所以第二次上线就出问题了。看着检查器,看起来所有的局部变量都不再在范围内了。

我还尝试将两种解决方案的代码放在另一种方法中,并在延迟后调用它,performSelector:withObject:afterDelay:但没有任何改变,即使是像 1 秒这样的长时间延迟。在第一个解决方案中,虽然没有发生断点上的双重命中。

在这一点上,我用完了解决方案,这对我来说似乎是一个 iOS 错误,但正如我所说,它在 Notes 应用程序中有效,所以至少有一个解决方案。

编辑:我做了更多调查,只有当文本视图是第一响应者并且显示键盘时才会发生错误(我不能说哪个负责)。如果我从代码而不是键盘通知触发 scrollRectToVisible:animated:,则动画效果很好。但是,如果我第一次调用[textView becomeFirstResponder]显示键盘的 ,动画会再次中断。

4

0 回答 0