ios 用属性字符串替换 UITextViews 文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16716525/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:41:49  来源:igfitidea点击:

Replace UITextViews text with attributed string

iosuitextviewcore-textnsattributedstring

提问by Georg

I have a UITextViewand when the user is entering text into it, I want to format the text on the fly. Something like syntax highlighting...

我有一个UITextView,当用户在其中输入文本时,我想即时格式化文本。像语法高亮这样的东西......

For that I'd like to use UITextView...

为此,我想使用UITextView...

Everything works fine expect one problem: I take the text from the text view and make an NSAttributedStringfrom of it. I make some edits to this attributed string and set it back as the textView.attributedText.

一切正常,但有一个问题:我从文本视图中获取文本并从中创建一个NSAttributedString。我对此属性字符串进行了一些编辑,并将其重新设置为textView.attributedText.

This happens everytime the user types. So I have to remember the selectedTextRangebefore the edit to the attributedTextand set it back afterwards so that the user can continue typing at the place he was typing before. The only problem is that once the text is long enough to require scrolling, the UITextViewwill now start scrolling to the top if I type slowly.

每次用户键入时都会发生这种情况。所以我必须记住selectedTextRange编辑之前的 并在attributedText之后将其设置回来,以便用户可以继续在他之前输入的地方输入。唯一的问题是,一旦文本足够长需要滚动,UITextView如果我输入缓慢,它现在将开始滚动到顶部。

Here is some sample code:

下面是一些示例代码:

- (void)formatTextInTextView:(UITextView *)textView
{
  NSRange selectedRange = textView.selectedRange;
  NSString *text = textView.text;

  // This will give me an attributedString with the base text-style
  NSMutableAttributedString *attributedString = [self attributedStringFromString:text];

  NSError *error = nil;
  NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"#(\w+)" options:0 error:&error];
  NSArray *matches = [regex matchesInString:text
                                    options:0
                                      range:NSMakeRange(0, text.length)];

  for (NSTextCheckingResult *match in matches)
  {
    NSRange matchRange = [match rangeAtIndex:0];
    [attributedString addAttribute:NSForegroundColorAttributeName
                             value:[UIColor redColor]
                             range:matchRange];
  }

  textView.attributedText = attributedString;
  textView.selectedRange = selectedRange;
}

Is there any solution without using CoreText directly? I like the UITextViews ability to select text and so on....

有没有不直接使用 CoreText 的解决方案?我喜欢UITextView选择文本等的能力....

回答by Sergey Kuryanov

I am not sure that this is correct solution, but it works.
Just disable scrolling before formatting text and enable it after formatting

我不确定这是正确的解决方案,但它有效。
只需在格式化文本之前禁用滚动并在格式化后启用它

- (void)formatTextInTextView:(UITextView *)textView
{
    textView.scrollEnabled = NO;
    NSRange selectedRange = textView.selectedRange;
    NSString *text = textView.text;

    // This will give me an attributedString with the base text-style
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:text];

    NSError *error = nil;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"#(\w+)" options:0 error:&error];
    NSArray *matches = [regex matchesInString:text
                                      options:0
                                        range:NSMakeRange(0, text.length)];

    for (NSTextCheckingResult *match in matches)
    {
        NSRange matchRange = [match rangeAtIndex:0];
        [attributedString addAttribute:NSForegroundColorAttributeName
                                 value:[UIColor redColor]
                                 range:matchRange];
    }

    textView.attributedText = attributedString;
    textView.selectedRange = selectedRange;
    textView.scrollEnabled = YES;
}

回答by Tapani

Used Sergeys's answer myself and ported it to Swift 2:

我自己使用了 Sergeys 的回答并将其移植到 Swift 2:

func formatTextInTextView(textView: UITextView) {
    textView.scrollEnabled = false
    let selectedRange = textView.selectedRange
    let text = textView.text

    // This will give me an attributedString with the base text-style
    let attributedString = NSMutableAttributedString(string: text)

    let regex = try? NSRegularExpression(pattern: "#(\w+)", options: [])
    let matches = regex!.matchesInString(text, options: [], range: NSMakeRange(0, text.characters.count))

    for match in matches {
        let matchRange = match.rangeAtIndex(0)
        attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: matchRange)
    }

    textView.attributedText = attributedString
    textView.selectedRange = selectedRange
    textView.scrollEnabled = true
}

回答by fugu2

In Swift 4:

在 Swift 4 中:

func createAttributedText() {
    let stringText = "Test String"
    let stringCount = stringText.count
    let string: NSMutableAttributedString = NSMutableAttributedString(string: stringText)

    string.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSMakeRange(0, stringCount))

    self.textView.attributedText =  string
}

回答by A.G

Swift 2.0:

斯威夫特 2.0:

let myDisplayTxt:String = "Test String"

    let string: NSMutableAttributedString = NSMutableAttributedString(string: self.myDisplayTxt)
    string.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: NSMakeRange(0, 5))
    string.addAttribute(String(kCTForegroundColorAttributeName), value: UIColor.redColor().CGColor as AnyObject, range: NSMakeRange(0, 5))

    self.sampleTextView.attributedText =  string