11

如何在粘贴板中复制 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 不是属性列表值。

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

4

4 回答 4

10

干净的解决方案不涉及 HTML,而是将 NSAttributedString 作为 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}];
}

斯威夫特 5

import MobileCoreServices

public extension UIPasteboard {
    func set(attributedString: NSAttributedString) {
        do {
            let rtf = try attributedString.data(from: NSMakeRange(0, attributedString.length), documentAttributes: [NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.rtf])
            items = [[kUTTypeRTF as String: NSString(data: rtf, encoding: String.Encoding.utf8.rawValue)!, kUTTypeUTF8PlainText as String: attributedString.string]]
        } catch {
        }
    }
}
于 2014-02-20T15:19:48.120 回答
10

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

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

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

它有效,但是:
转换为 html 格式意味着我将丢失自定义属性。任何干净的解决方案都将被欣然接受。

文件 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 上,请成为我的客人 :)

于 2012-09-26T13:45:30.087 回答
1

这很简单:

  #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];
于 2016-11-17T06:05:51.863 回答
-1

OSX 中的粘贴板管理器可以在许多文本和图像类型之间自动转换。

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

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

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

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

于 2013-03-11T21:53:37.867 回答