其他应用程序在 iOS 5 中粘贴 HTML,而不是粘贴板数据的文​​本版本

发布于 2024-12-10 16:53:42 字数 907 浏览 3 评论 0原文

我们有一个现有的应用程序,允许用户将文本复制到粘贴板。如果可能,我们将 HTML 和纯文本都放在剪贴板上,因为我们不知道用户可能粘贴到哪个其他应用程序中,并且希望提供格式化 (HTML) 和未格式化的数据。

此功能在 iOS 3 和 4 中运行良好。但是,一旦用户安装 iOS 5,当他们将我们的应用程序中的文本粘贴到任何其他应用程序时,其他应用程序会获取 HTML 文本,但将其视为纯文本。因此,如果他们选择并复制 H1 标题,当他们粘贴到其他应用程序时,他们不会看到“这是一个标题”,而是看到“

这是一个标题

”。

请注意,这是在 iOS 3 和 4 中正常工作的现有代码。在 iOS 3、4 和 5 之间,我们的代码没有任何变化。

为了完整起见,这里是我们用来将文本放在粘贴板上的代码,使用一个简单的代码提供的字符串仅供参考:

NSString * plainText = @"A Big Heading\r\nA regular paragraph.";
NSString * htmlText = @"<h1>A Big Heading</h1><p>A regular paragraph.</p>";
UIPasteboard * pasteboard = [UIPasteboard generalPasteboard];
pasteboard.items = [NSArray arrayWithObject:
    [NSDictionary dictionaryWithObjectsAndKeys:
        plainText, @"public.utf8-plain-text", htmlText, @"public.html", nil]];

显然,我的问题是“为什么 iOS 5 应用程序在请求纯文本时会获取 HTML 文本,而在 iOS 4 下运行的同一应用程序会获取纯文本?”

We have an existing app that allows the user to copy text to the pasteboard. When possible, we put both HTML and plain text on the clipboard, since we don't know what other app the user might be pasting into and want to provide both formatted (HTML) and unformatted data.

This functionality works great in iOS 3 and 4. But as soon as the user installs iOS 5, when they paste text from our app into any other app, the other app gets the HTML text but treats it as plain text. So if they select and copy an H1 heading, when they paste into the other app, instead of seeing "This is a Heading", they see "<h1>This is a Heading</h1>".

Note that this is with existing code that works fine in iOS 3 and 4. There's no change to our code between iOS 3, 4, and 5.

For completeness, here's the code we use to put our text on the pasteboard, with a simple string provided just for reference:

NSString * plainText = @"A Big Heading\r\nA regular paragraph.";
NSString * htmlText = @"<h1>A Big Heading</h1><p>A regular paragraph.</p>";
UIPasteboard * pasteboard = [UIPasteboard generalPasteboard];
pasteboard.items = [NSArray arrayWithObject:
    [NSDictionary dictionaryWithObjectsAndKeys:
        plainText, @"public.utf8-plain-text", htmlText, @"public.html", nil]];

Obviously, my question is "Why do iOS 5 apps get the HTML text when they request plain text, while the same app running under iOS 4 gets the plain text?"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

大姐,你呐 2024-12-17 16:53:42

对于那些在家玩的人来说,这是我们发现的答案。

在将包含未格式化文本的 NSString 放入粘贴板时,“public.utf8-plain-text”历来都是正确的 UTI。内置控件在“粘贴”操作期间控制所有请求并使用此版本的粘贴板内容(适用于 5 之前的 iOS 版本)。如果您仅在粘贴板中放入“public.plain-text”或“public.text”文本,内置控件将完全忽略它,并说粘贴板是空的(不给您“粘贴”选项)。

在 iOS 5 中,有些事情发生了变化,当内置控件在上述情况下请求纯文本时,它们将获得“public.html”文本。

对于 iOS 5,您必须使用“public.text”而不是“public.plain-text”或“public.utf8-plain-text”,尽管后两者可以说更正确,而前者太模糊而无法使用全部。

由于早期的 iO​​S 版本忽略“public.text”,我们的解决方案是将所有三个版本放在粘贴板上:“public.text”和“public.utf8-plain-text”都会为您提供纯文本,而“public.html” " 将为您提供 HTML 文本。这似乎可以满足 iOS 4 和 5,而无需在代码中放置显式的 iOS 版本测试,代价是在字典中多了一个条目。

苹果公司的孩子们又遭遇了一次失败。

编辑 2016 年和 iOS 8/9

自从我发布这个问题以来,我一直在尝试一劳永逸地解决这个问题。每当我用谷歌搜索时,我总是会回到这个问题。

在此过程中,iOS 引入了“网络存档”概念,用于将 HTML 放在粘贴板上。任何地方都没有很好的记录。我在这里找到了答案 这早于我的问题,所以这有点令人沮丧,但它有效。我对其进行了更新,以利用更高版本的 iOS 中内置的 base64 编码。事情是这样的:

NSMutableDictionary * contents = [NSMutableDictionary dictionaryWithCapacity:6];
NSString * htmlText = @"<h1>A Heading</h1><p>A paragraph.</p>"
//... put other formats in the dictionary, then...
NSData * data = [htmlText dataUsingEncoding:NSUTF8StringEncoding];
NSString * base64encodedString = [data base64EncodedStringWithOptions:0];
NSString * webArchiveString = [NSString stringWithFormat:
    @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
    "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
    "<plist version=\"1.0\">"
    "<dict>"
    "<key>WebMainResource</key>"
    "<dict>"
    "<key>WebResourceData</key>"
    "<data>%@</data>"
    "<key>WebResourceFrameName</key>"
    "<string></string>"
    "<key>WebResourceMIMEType</key>"
    "<string>text/html</string>"
    "<key>WebResourceTextEncodingName</key>"
    "<string>UTF-8</string>"
    "<key>WebResourceURL</key>"
    "<string>about:blank</string>"
    "</dict>"
    "</dict>"
    "</plist>", base64encodedString];
[contents setObject:webArchiveString forKey:@"Apple Web Archive pasteboard type"];
UIPasteboard * pasteboard = [UIPasteboard generalPasteboard];
pasteboard.items = [NSArray arrayWithObject:contents];

For those of you playing along at home, here's the answer we discovered.

"public.utf8-plain-text" has historically been the correct UTI to use when putting an NSString containing unformatted text into the pasteboard. The built-in controls all request and use this version of the pasteboard contents during their "paste" operations (for iOS versions prior to 5). If you put only "public.plain-text" or "public.text" text in the pasteboard, the built-in controls ignore it completely, saying the pasteboard is empty (not giving you the "paste" option).

In iOS 5, something changed and when the built-in controls request plain text in the situation above, they will get the "public.html" text.

For iOS 5 you must use "public.text" instead of "public.plain-text" or "public.utf8-plain-text" even though the latter two are arguably more correct and the former is too vague to be of use at all.

Since earlier iOS versions ignore "public.text", our solution is to put all three versions on the pasteboard: "public.text" and "public.utf8-plain-text" will both get you the plain text and "public.html" will get you the HTML text. This seems to satisfy both iOS 4 and 5 without having to put an explicit iOS version test in the code, at the cost of one more entry in the dictionary.

One more fail for the kids at Apple.

EDIT for 2016 and iOS 8/9

I've been trying to solve this problem once and for all ever since I posted this question. Whenever I do a Google search, I always end up back at this question.

Somewhere along the line, iOS introduced a "web archive" concept for putting HTML on the pasteboard. It's not documented well anywhere. I found an answer here which pre-dates my question, so that's a little frustrating, but it works. I've updated it to take advantage of built-in base64 encoding in later versions of iOS. It goes something like this:

NSMutableDictionary * contents = [NSMutableDictionary dictionaryWithCapacity:6];
NSString * htmlText = @"<h1>A Heading</h1><p>A paragraph.</p>"
//... put other formats in the dictionary, then...
NSData * data = [htmlText dataUsingEncoding:NSUTF8StringEncoding];
NSString * base64encodedString = [data base64EncodedStringWithOptions:0];
NSString * webArchiveString = [NSString stringWithFormat:
    @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
    "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
    "<plist version=\"1.0\">"
    "<dict>"
    "<key>WebMainResource</key>"
    "<dict>"
    "<key>WebResourceData</key>"
    "<data>%@</data>"
    "<key>WebResourceFrameName</key>"
    "<string></string>"
    "<key>WebResourceMIMEType</key>"
    "<string>text/html</string>"
    "<key>WebResourceTextEncodingName</key>"
    "<string>UTF-8</string>"
    "<key>WebResourceURL</key>"
    "<string>about:blank</string>"
    "</dict>"
    "</dict>"
    "</plist>", base64encodedString];
[contents setObject:webArchiveString forKey:@"Apple Web Archive pasteboard type"];
UIPasteboard * pasteboard = [UIPasteboard generalPasteboard];
pasteboard.items = [NSArray arrayWithObject:contents];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文