如何允许NSAttributedString文本输入到UITextView?

12

我正在尝试让UITextView支持输入不同样式的文本,就像一个使用简单属性(如加粗或斜体)的文本编辑器。通过使用textView的attributedText属性,我可以将属性应用于特定文本范围。虽然这很好,但我希望能够在textView中键入带有属性的文本,并通过按钮(例如键入粗体文本)切换。

到目前为止,我想到了以下方法:

我使用了-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text UITextView委托方法来获取text参数,并创建一份具有相同文本的NSAttributedString来修改它的属性。然后创建一个NSMutableAttributedString,它是textView的attributedText的副本。使用appendAttributedString将两者连接起来,然后将textView的attributedText属性设置为结果attributedString。

这是代码:

-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

   if (self.boldPressed) {

        UIFont *boldFont = [UIFont boldSystemFontOfSize:self.textView.font.pointSize];
        NSDictionary *boldAttr = [NSDictionary dictionaryWithObject:boldFont forKey:NSFontAttributeName];
        NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc]initWithString:text attributes:boldAttr];
        NSMutableAttributedString *textViewText = [[NSMutableAttributedString alloc]initWithAttributedString:textView.attributedText];
        [textViewText appendAttributedString:attributedText];
        textView.attributedText = textViewText;

           return NO;
       }
   return YES;                
}

每次键入一个字符都必须重置textViews的attributedText,这似乎对于一个简单的操作来说有些过度了。而且它也不能正常工作。当启用粗体属性时,它看起来像这样:

attributedText issues

这里有两个问题。最明显的问题是每个新字符都放在新行上。但更奇怪的是插入点总是在textview文本的第一个索引处(仅当启用粗体时,然后粗体字符就会插入到新行中)。因此,如果您使用粗体键入,然后关闭粗体,键入将在所有现有文本之前恢复。

我不确定为什么会出现这些错误。我也不认为我的解决方案很有效,但我想不出其他实现方法。


1
这应该可以工作, 我认为这是一个很好的技巧. 你能加些日志信息吗? 另外, 为什么不总是写属性字符串 - 永远不返回YES呢? 你可以有一个阴影属性字符串来维护,并且总是在那个委托方法中设置它,而不是混合使用普通和属性字符串。如果失败了,上传一个只有这个代码的演示应用程序,然后有人(比如我)会看一下的。我有99%的把握你可以让它工作(但我自己没有这样做过)。 - David H
结果发现必须使用typingAttributes属性,正如您在其他答案中所看到的那样。添加一些日志消息最终引起了更多问题而不是答案,因为所有附加到textView的attributedText的NSAttributedStrings都将始终进入新行...这导致我得出结论,在shouldChangeTextInRange方法中无法实现它(因此设置setTypingAttributes属性)。仍然不确定原因,但设置typingAttributes似乎是一个更优雅的解决方案。 - Joe
哈哈,这就是为什么Rob Napier有70K积分的原因!很高兴你找到了解决方案 - 我确信一定有一个! - David H
2个回答

39

这就是setTypingAttributes:的作用。当用户按下您所设置的属性按钮时,请将其设置为您的属性字典,新字符将使用请求的属性。


谢谢,我不知道这个存在。当您不再需要使用它时,如何删除属性?我尝试将typingAttributes属性设置为空字典,但这会删除所有其他属性,例如字体大小。该属性不可变,因此无法删除最后添加的属性。 - Joe
制作当前值的“mutableCopy”。进行修改,然后重新分配它。 - Rob Napier
好的,明白了。非常感谢。 - Joe

7
如果您正在寻找示例,下面是一些样本代码来实现这个目标。 Swift 3.0
var attributes = textField.typingAttributes
attributes["\(NSForegroundColorAttributeName)"] = UIColor.red
textField.typingAttributes = attributes

Objective-C

NSMutableDictionary* attributes = [textField.typingAttributes mutableCopy];
attributes[NSForegroundColorAttributeName] = [UIColor redColor];
textField.typingAttributes = attributes;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接