在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”。