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

Cra*_*aig 3 iphone uipasteboard uti ipad ios5

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

此功能在iOS 3和4中运行良好.但是一旦用户安装iOS 5,当他们将我们的应用程序中的文本粘贴到任何其他应用程序时,另一个应用程序将获取HTML文本但将其视为纯文本.因此,如果他们选择并复制H1标题,当他们粘贴到另一个应用程序时,而不是看到"这是一个标题",他们会看到"<h1>这是一个标题</ 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]];
Run Code Online (Sandbox Code Playgroud)

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

Cra*_*aig 6

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

历史上,"public.utf8-plain-text"在将包含无格式文本的NSString放入粘贴板时使用的是正确的UTI.内置控件在"粘贴"操作期间(对于5之前的iOS版本)请求并使用此版本的粘贴板内容.如果你只在粘贴板中放入"public.plain-text"或"public.text"文本,内置控件会完全忽略它,说粘贴板是空的(没有给你"粘贴"选项).

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

对于iOS 5,您必须使用"public.text"而不是"public.plain-text"或"public.utf8-plain-text",即使后两者可以说更正确而且前者太模糊而无法使用所有.

由于早期的iOS版本忽略了"public.text",我们的解决方案是将所有三个版本放在粘贴板上:"public.text"和"public.utf8-plain-text"将为您提供纯文本和"public.html" "会得到你的HTML文字.这似乎满足iOS 4和5,无需在代码中放置明确的iOS版本测试,代价是字典中的一个条目.

Apple的孩子们还有一个失败.

编辑2016年和iOS 8/9

自从我发布这个问题以来,我一直试图一劳永逸地解决这个问题.每当我进行谷歌搜索时,我总会回到这个问题.

在某个地方,iOS引入了一个"web存档"概念,用于将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];
Run Code Online (Sandbox Code Playgroud)