UITextView撤消管理器不适用于替换属性字符串(iOS 6)



iOS 6已更新为使用UITextView进行富文本编辑(UITextView现在获得了attributedText属性,这是愚蠢的不可变属性)。以下是在NDA下的iOS 6苹果论坛上提出的一个问题,该问题可以公开,因为iOS 6现在已经公开了。。。

在UITextView中,我可以撤消任何字体更改,但不能撤消视图属性字符串副本中的替换。使用此代码时。。。

- (void) replace: (NSAttributedString*) old with: (NSAttributedString*) new
{
1.    [[myView.undoManager prepareWithInvocationTarget:self] replace:new with:old];
2.    old=new;
}

撤销是很有效的。

但是,如果我添加一行以使结果在视图中可见,undoManager不会像它应该的那样激发"replace:with:"方法。。。

- (void) replace: (NSAttributedString*) old with: (NSAttributedString*) new
{
1.    [[myView.undoManager prepareWithInvocationTarget:self] replace:new with:old];
2.    old=new;
3.    myView.attributedText=[[NSAttributedString alloc] initWithAttributedString:old];
}

知道吗?我对任何替换方法都有同样的问题,无论是否使用范围,对于我试图在第"2"行使用的MutableAttributedString。。。

嗯,哇,我真的没想到会这样!我找不到解决方案,所以我开始尝试一切。。。

- (void)applyAttributesToSelection:(NSDictionary*)attributes {
UITextView *textView = self.contentCell.textView;
NSRange selectedRange = textView.selectedRange;
UITextRange *selectedTextRange = textView.selectedTextRange;
NSAttributedString *selectedText = [textView.textStorage attributedSubstringFromRange:selectedRange];
[textView.undoManager beginUndoGrouping];
[textView replaceRange:selectedTextRange withText:selectedText.string];
[textView.textStorage addAttributes:attributes range:selectedRange];
[textView.undoManager endUndoGrouping];
[textView setTypingAttributes:attributes];
}

UITextViewundoManager,它将免费管理撤消和重做,而不需要任何额外的代码。

替换其attributedText将重置undoManager(更新textStorage中的文本及其属性对我也不起作用)。然而,我发现,在不替换attributedText而是通过标准编辑操作(右键单击高亮显示文本>字体>粗体(Mac Catalyst))设置文本格式时,撤消和重做功能可以正常工作。

为了确保undoManager正常工作,您只需要使用UITextView的某些特定方法。使用其他方法可能会破坏UITextView的撤消功能。

编辑文本

  1. 您需要将UITextViewallowsEditingTextAttributes设置为true,这将使UITextView支持对attributedText的撤消和重做
self.textView.allowsEditingTextAttributes = true
  1. 如果要更改attributedText的文本,请使用UITextInputreplace(_:withText:),或UITextView符合的UIKeyInputinsertText(_:)deleteBackward()
self.textView.replace(self.textView.selectedTextRange!, withText: "test")

更新属性

如果要更改文本的属性,请改用UITextView中的updateTextAttributes(conversionHandler:)

self.textView.updateTextAttributes { _ in

let font = UIFont.boldSystemFont(ofSize: 17)
let attributes: [NSAttributedString.Key: Any] = [
.font: font,
]

return attributes
}

self.textView.updateTextAttributes { attributes in

let newAttributes = attributes
let font = UIFont.boldSystemFont(ofSize: 17)
let newAttributes: [.font] = font

return newAttributes
}

插入附件

根据NSAttributedStringinit(attachment:)的文档。

这是一种方便的方法,用于创建包含附件的属性字符串,该字符串使用character(NSTextAttachment.fcharacter)作为基字符。

如果要使用updateTextAttributes添加附件,则应首先为附件(NSTextAttachment.character)插入一个特殊字符(如果不使用此字符,则附件不会显示)。

例如,

let attachment = NSTextAttachment(image: image)
let specialChar = String(Character(UnicodeScalar(NSTextAttachment.character)!))
textView.insertText(specialChar)
textView.selectedRange = NSRange(location: textView.selectedRange.lowerBound-specialChar.count, length: specialChar.count)
textView.updateTextAttributes { attributes in

var newAttributes = attributes
newAttributes[.attachment] = attachment
return newAttributes

}

若要更改特定范围内的文本及其属性,请修改UITextViewselectedRangeselectedTextRange

要实现撤消和重做按钮,请检查以下答案:https://stackoverflow.com/a/50530040/8637708

我已经用Mac Catalyst进行了测试,它应该也能在iOS和iPadOS上运行。

撤销管理器在设置其"text"或"attributedText"属性后重置,这就是它不起作用的原因。我不知道这种行为是错误还是故意的。

但是,您可以使用UITextInput协议方法。

  • (void)replaceRange:(UITextRange*)range with text:(NSString*)text

这很有效。

相关内容

  • 没有找到相关文章

最新更新