解决方法
我不知道如果在iOS 7中省略了向上和向下箭头键支持是有意的.这里有一种恢复约95%的丢失能力的方法.请注意,UITextView的这个子类还会修正iOS 7中的一些问题,其中滚动文本视图会导致它跳动.我已经看到它从中途跳过一个长文件到文件的末尾.
我发现这个实现的唯一问题是重复键os没有处理,所以如果你按住向上或向下箭头键,移动光标的代码仍然只被称为一次.
- #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
- @implementation ArrowKeyTextView
- - (id) initWithFrame: (CGRect) frame {
- self = [super initWithFrame:frame];
- if (self) {
- // This has nothing to do with support for arrow keys,but it does fix a number of issues with scrolling in iOS 7.
- if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
- self.layoutManager.allowsNonContiguousLayout = NO;
- }
- return self;
- }
- - (NSArray *) keyCommands {
- UIKeyCommand *upArrow = [UIKeyCommand keyCommandWithInput: UIKeyInputUpArrow modifierFlags: 0 action: @selector(upArrow:)];
- UIKeyCommand *downArrow = [UIKeyCommand keyCommandWithInput: UIKeyInputDownArrow modifierFlags: 0 action: @selector(downArrow:)];
- return [[NSArray alloc] initWithObjects: upArrow,downArrow,nil];
- }
- - (void) upArrow: (UIKeyCommand *) keyCommand {
- UITextRange *range = self.selectedTextRange;
- if (range != nil) {
- float lineHeight = self.font.lineHeight;
- CGRect caret = [self firstRectForRange: range];
- if (isinf(caret.origin.y)) {
- // Work-around for a bug in iOS 7 that returns bogus values when the caret is at the start of a line.
- range = [self textRangeFromPosition: range.start toPosition: [self positionFromPosition: range.start offset: 1]];
- caret = [self firstRectForRange: range];
- caret.origin.y = caret.origin.y + lineHeight;
- }
- caret.origin.y = caret.origin.y - lineHeight < 0 ? 0 : caret.origin.y - lineHeight;
- caret.size.width = 1;
- UITextPosition *position = [self closestPositionToPoint: caret.origin];
- self.selectedTextRange = [self textRangeFromPosition: position toPosition: position];
- caret = [self firstRectForRange: self.selectedTextRange];
- if (isinf(caret.origin.y)) {
- // Work-around for a bug in iOS 7 that occurs when the range is set to a position past the end of the last character
- // on a line.
- NSRange range = {0,0};
- range.location = [self offsetFromPosition: self.beginningOfDocument toPosition: position];
- self.selectedRange = range;
- }
- }
- }
- - (void) downArrow: (UIKeyCommand *) keyCommand {
- UITextRange *range = self.selectedTextRange;
- if (range != nil) {
- float lineHeight = self.font.lineHeight;
- CGRect caret = [self firstRectForRange: range];
- if (isinf(caret.origin.y)) {
- // Work-around for a bug in iOS 7 that returns bogus values when the caret is at the start of a line.
- range = [self textRangeFromPosition: range.start toPosition: [self positionFromPosition: range.start offset: 1]];
- caret = [self firstRectForRange: range];
- caret.origin.y = caret.origin.y + lineHeight;
- }
- caret.origin.y = caret.origin.y + lineHeight < 0 ? 0 : caret.origin.y + lineHeight;
- caret.size.width = 1;
- UITextPosition *position = [self closestPositionToPoint: caret.origin];
- self.selectedTextRange = [self textRangeFromPosition: position toPosition: position];
- caret = [self firstRectForRange: self.selectedTextRange];
- if (isinf(caret.origin.y)) {
- // Work-around for a bug in iOS 7 that occurs when the range is set to a position past the end of the last character
- // on a line.
- NSRange range = {0,0};
- range.location = [self offsetFromPosition: self.beginningOfDocument toPosition: position];
- self.selectedRange = range;
- }
- }
- }
- @end