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
Replace UITextViews text with attributed string
提问by Georg
I have a UITextView
and 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 NSAttributedString
from 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 selectedTextRange
before the edit to the attributedText
and 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 UITextView
will 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 UITextView
s 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