我遇到了类似的问题,包括“如果我将动画设置为 NO,一切都按预期工作”部分。
事实证明,在 iOS 6 上,UITextView 自动滚动其最近的父 UIScrollView 以使光标在成为第一响应者时可见。在 iOS 7 上没有这样的行为。UIScrollView 似乎对同时两次调用 scrollRectToVisible 感到困惑。
在 iOS 6 上,我对 scrollRectToVisible 的显式调用大部分时间都被忽略了。它只会滚动以使 UITextView 的第一行可见(自动滚动),而不是像在 iOS 7 上所做的那样。
为了测试它,在 Xcode 5 中创建一个新的单视图应用程序,将其部署目标设置为 6.0 并将下面的代码用于 ViewController.m。在 iOS 6.1 模拟器中运行它,滚动以隐藏 UITextView,然后点击屏幕上的任意位置。您可能需要重试几次,但在大多数情况下,它只会使第一行可见。如果您重新启用 WORKAROUD 定义,则 UITextView 将嵌入到其自己的 UIScrollView 中,并且对 scrollRectToVisible 的调用按预期工作。
#import "ViewController.h"
//#define WORKAROUND
@interface ViewController ()
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UITextView *textView;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewTap)]];
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 240)];
self.scrollView.contentSize = CGSizeMake(320, 400);
self.scrollView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.scrollView];
#ifdef WORKAROUND
UIScrollView* dummyScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, 280, 280, 100)];
self.textView = [[UITextView alloc] initWithFrame:dummyScrollView.bounds];
[dummyScrollView addSubview:self.textView];
[self.scrollView addSubview:dummyScrollView];
#else
self.textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 280, 280, 100)];
[self.scrollView addSubview:self.textView];
#endif
self.textView.backgroundColor = [UIColor grayColor];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)viewTap
{
if (self.textView.isFirstResponder) {
[self.textView resignFirstResponder];
}
else {
[self.textView becomeFirstResponder];
}
}
- (void)keyboardWasShown:(NSNotification*)aNotification
{
#ifdef WORKAROUND
[self.scrollView scrollRectToVisible:CGRectInset(self.textView.superview.frame, 0, -10) animated:YES];
#else
[self.scrollView scrollRectToVisible:CGRectInset(self.textView.frame, 0, -10) animated:YES];
#endif
}
@end