从NSRange创建UITextRange

Joh*_*und 48 objective-c uitextview nsrange ios5

我需要在textview中找到不同范围的像素帧.我正在用- (CGRect)firstRectForRange:(UITextRange *)range;它来做.但是我无法找到如何实际创建一个UITextRange.

基本上这就是我要找的东西:

- (CGRect)frameOfTextRange:(NSRange)range inTextView:(UITextView *)textView {

    UITextRange*range2 = [UITextRange rangeWithNSRange:range]; //DOES NOT EXIST 
    CGRect rect = [textView firstRectForRange:range2];
    return rect;
}
Run Code Online (Sandbox Code Playgroud)

Apple表示必须进行子类化UITextRangeUITextPosition采用该UITextInput协议.我不这样做,但无论如何,我尝试了,遵循doc的示例代码并传递firstRectForRange导致崩溃的子类.

如果有更简单的方法UILables可以在textview 中添加不同的颜色,请告诉我.我尝试使用content editable设置为TRUE的UIWebView ,但我不喜欢与JS通信,并且着色是我唯一需要的东西.

提前致谢.

Nic*_*idt 90

您可以使用该方法创建文本范围textRangeFromPosition:toPosition.此方法需要两个位置,因此您需要计算范围开始和结束的位置.这是通过该方法完成的,该方法positionFromPosition:offset从另一个位置返回一个位置和一个字符偏移量.

- (CGRect)frameOfTextRange:(NSRange)range inTextView:(UITextView *)textView
{
    UITextPosition *beginning = textView.beginningOfDocument;
    UITextPosition *start = [textView positionFromPosition:beginning offset:range.location];
    UITextPosition *end = [textView positionFromPosition:start offset:range.length];
    UITextRange *textRange = [textView textRangeFromPosition:start toPosition:end];
    CGRect rect = [textView firstRectForRange:textRange];
    return [textView convertRect:rect fromView:textView.textInputView];
}
Run Code Online (Sandbox Code Playgroud)

  • 我有一个小小的评论.这仅在TextField是第一个响应者时有效.否则所有位置都将为NULL,而rect的大小分别为零.如果有人提示如何在没有TextField作为第一响应者的情况下获得矩形,请与我们分享. (6认同)
  • 文本系统是过度设计的 (5认同)

auc*_*uco 17

这看起来有点复杂,有点荒谬.一个简单的"解决方法"是选择范围(接受NSRange),然后读取selectedTextRange(返回UITextRange):

- (CGRect)frameOfTextRange:(NSRange)range inTextView:(UITextView *)textView {
    textView.selectedRange = range;
    UITextRange *textRange = [textView selectedTextRange]; 
    CGRect rect = [textView firstRectForRange:textRange];
    return rect;
}
Run Code Online (Sandbox Code Playgroud)

即使textView不是第一响应者,这对我也有用.


如果您不希望选择保持不变,则可以重置selectedRange:

textView.selectedRange = NSMakeRange(0, 0);
Run Code Online (Sandbox Code Playgroud)

...或保存当前选择并在之后恢复

NSRange oldRange = textView.selectedRange;
// do something
// then check if the range is still valid and
textView.selectedRange = oldRange;
Run Code Online (Sandbox Code Playgroud)


And*_*ber 6

对于标题问题,这是一个Swift 2扩展,它从NSRange创建一个UITextRange.

UITextRange的唯一初始化器是UITextInput协议上的实例方法,因此扩展还要求您传入UITextInput,例如UITextFieldUITextView.

extension NSRange {
    func toTextRange(textInput textInput:UITextInput) -> UITextRange? {
        if let rangeStart = textInput.positionFromPosition(textInput.beginningOfDocument, offset: location),
            rangeEnd = textInput.positionFromPosition(rangeStart, offset: length) {
            return textInput.textRangeFromPosition(rangeStart, toPosition: rangeEnd)
        }
        return nil
    }
}
Run Code Online (Sandbox Code Playgroud)


Cod*_*ess 6

Swift 4的Andrew Schreiber的答案是轻松复制/粘贴

extension NSRange {
    func toTextRange(textInput:UITextInput) -> UITextRange? {
        if let rangeStart = textInput.position(from: textInput.beginningOfDocument, offset: location),
            let rangeEnd = textInput.position(from: rangeStart, offset: length) {
            return textInput.textRange(from: rangeStart, to: rangeEnd)
        }
        return nil
    }
}
Run Code Online (Sandbox Code Playgroud)