在UIPasteBoard中复制NSAttributedString

如何复制剪贴板中的NSAttributedString ,以允许用户粘贴或以编程方式粘贴(使用- (void)paste:(id)sender ,从UIResponderStandardEditActions协议)。

我试过了:

 UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard]; [pasteBoard setValue:attributedString forPasteboardType:(NSString *)kUTTypeRTF]; 

但是这个崩溃与:

 -[UIPasteboard setValue:forPasteboardType:]: value is not a valid property list type' 

这是可以预料的,因为NSAttributedString不是一个属性列表值。

如果用户将粘贴板的内容粘贴到我的应用程序中,我想保留属性string的所有标准和自定义属性。

我发现,当我(作为应用程序的用户)从UITextView复制富文本到粘贴板时,粘贴板包含两种types:

 "public.text", "Apple Web Archive pasteboard type 

基于此,我在UIPasteboard上创build了一个便利的类别。
(大量使用这个答案的代码)。

它可以工作,但是:
转换为html格式意味着我将失去自定义属性。 任何干净的解决scheme将很乐意接受。

文件UIPasteboard + AttributedString.h:

 @interface UIPasteboard (AttributedString) - (void) setAttributedString:(NSAttributedString *)attributedString; @end 

文件UIPasteboard + AttributedString.m:

 #import <MobileCoreServices/UTCoreTypes.h> #import "UIPasteboard+AttributedString.h" @implementation UIPasteboard (AttributedString) - (void) setAttributedString:(NSAttributedString *)attributedString { NSString *htmlString = [attributedString htmlString]; // This uses DTCoreText category NSAttributedString+HTML - https://github.com/Cocoanetics/DTCoreText NSDictionary *resourceDictionary = @{ @"WebResourceData" : [htmlString dataUsingEncoding:NSUTF8StringEncoding], @"WebResourceFrameName": @"", @"WebResourceMIMEType" : @"text/html", @"WebResourceTextEncodingName" : @"UTF-8", @"WebResourceURL" : @"about:blank" }; NSDictionary *htmlItem = @{ (NSString *)kUTTypeText : [attributedString string], @"Apple Web Archive pasteboard type" : @{ @"WebMainResource" : resourceDictionary } }; [self setItems:@[ htmlItem ]]; } @end 

只实施了setter。 如果你想写getter,并且/或者把它放在GitHub上,成为我的客人:)

@ Guillaume的方法使用HTML不适用于我(至less在iOS 7.1 beta 5中)。

更干净的解决scheme是将NSAttributedStrings作为RTF(加上明文回退)插入到粘贴板中:

 - (void)setAttributedString:(NSAttributedString *)attributedString { NSData *rtf = [attributedString dataFromRange:NSMakeRange(0, attributedString.length) documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType} error:nil]; self.items = @[@{(id)kUTTypeRTF: [[NSString alloc] initWithData:rtf encoding:NSUTF8StringEncoding], (id)kUTTypeUTF8PlainText: attributedString.string}]; } 

Swift 2.3

 public extension UIPasteboard { public func set(attributedString: NSAttributedString?) { guard let attributedString = attributedString else { return } do { let rtf = try attributedString.dataFromRange(NSMakeRange(0, attributedString.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType]) items = [[kUTTypeRTF as String: NSString(data: rtf, encoding: NSUTF8StringEncoding)!, kUTTypeUTF8PlainText as String: attributedString.string]] } catch { } } } 

Swift 3

 import MobileCoreServices public extension UIPasteboard { public func set(attributedString: NSAttributedString?) { guard let attributedString = attributedString else { return } do { let rtf = try attributedString.data(from: NSMakeRange(0, attributedString.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType]) items = [[kUTTypeRTF as String: NSString(data: rtf, encoding: String.Encoding.utf8.rawValue)!, kUTTypeUTF8PlainText as String: attributedString.string]] } catch { } } } 

这很简单:

  #import <MobileCoreServices/UTCoreTypes.h> NSMutableDictionary *item = [[NSMutableDictionary alloc] init]; NSData *rtf = [attributedString dataFromRange:NSMakeRange(0, attributedString.length) documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType} error:nil]; if (rtf) { [item setObject:rtf forKey:(id)kUTTypeFlatRTFD]; } [item setObject:attributedString.string forKey:(id)kUTTypeUTF8PlainText]; UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; pasteboard.items = @[item]; 

OSX中的粘贴板pipe理器可以在很多文本和图像types之间自动转换。

对于富文本types,您通常会将RTF放入粘贴板。 您可以从属性string创buildRTF表示forms,反之亦然。 请参阅“NSAttributedString应用程序工具包添加参考”。

如果您还包含图像,则使用RTFd而不是RTF风格。

我不知道这些MIMEtypes(我习惯于Carbon Pasteboard API,而不是Cocoa API),但是您可以使用UTType API在UTI,Pboard和MIMEtypes之间进行转换。

用于RTF的UTI是“public.rtf”,对于RTFd是“com.apple.flat-rtfd”。