Dan*_*row 5 nsattributedstring nstextattachment ios ios7
我有一些非常简单的RTF文件输出。当我生成此文档时,用户可以通过电子邮件发送该文档。所有这些都很好。该文档看起来不错。一旦有了NSAttributedString,就制作一个NSData块,并将其写入文件,如下所示:
NSData* rtfData = [attrString dataFromRange:NSMakeRange(0, [attrString length]) documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType} error:&error];
Run Code Online (Sandbox Code Playgroud)
该文件可以通过电子邮件发送。当我检查电子邮件时,一切都很好。
现在,我的任务是在文档顶部添加UIImage。太好了,所以我正在创建这样的属性字符串:
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
UIImage* image = [UIImage imageNamed:@"logo"];
attachment.image = image;
attachment.bounds = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
NSMutableAttributedString *imageAttrString = [[NSAttributedString attributedStringWithAttachment:attachment] mutableCopy];
// sets the paragraph styling of the text attachment
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init] ;
[paragraphStyle setAlignment:NSTextAlignmentCenter]; // centers image horizontally
[paragraphStyle setParagraphSpacing:10.0f]; // adds some padding between the image and the following section
[imageAttrString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [imageAttrString length])];
[imageAttrString appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\n"]];
Run Code Online (Sandbox Code Playgroud)
此时,在Xcode中,我可以对imageAttrString进行QuickLook,它可以很好地绘制。
构建此字符串后,我将执行以下操作:
[attrString appendAttributedString:imageAttrString];
Run Code Online (Sandbox Code Playgroud)
然后添加我最初生成的所有其余属性文本。
现在查看文件时,没有图像。QuickLook在调试器中看起来不错,但最终输出中没有图像。
在此先感谢您的任何帮助。
尽管RTF确实支持Windows上的嵌入式图像,但显然不支持OSX。RTF由Microsoft开发,他们在1.5版中添加了嵌入式图像(http://en.wikipedia.org/wiki/Rich_Text_Format#Version_changes)。我认为Apple采用了该格式的较早版本,并且他们对文档中图像的解决方案是RTFD。这是Apple文档关于RTF的内容:
RTF格式(RTF)是Microsoft Corporation设计的一种文本格式语言。您可以使用纯文本以及散布的RTF命令,组和转义序列来表示字符,段落和文档格式属性。RTF被广泛用作文档交换格式,以跨应用程序和计算平台传输文档及其格式信息。Apple通过自定义命令扩展了RTF,本章对此进行了介绍。
因此没有提及图像。最后,要证明RTF在Mac上不支持图像,请下载此RTF文档 -它会在Windows写字板中显示照片,而不会在OS X TextEdit中显示。
因此,正如Larme所说-添加附件时,您应该选择RTFD文件类型。从维基百科:
富文本格式目录,也称为RTFD(由于其扩展名为.rtfd)或带附件的富文本格式
尽管您将能够获取同时包含文本和图像的NSData对象(根据其大小判断),但是通过dataFromRange:documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType} error:]您可能无法保存它,以便可以成功打开它。至少-我做不到。
这可能是因为RTFD实际上不是文件格式,而是捆绑格式。要检查它,您可以在Mac上使用TextEdit来创建一个新文档,向其中添加图像和文本并将其另存为文件。然后右键单击该文件,然后选择“显示软件包内容”,您会注意到该目录同时包含您的图像和RTF格式的文本。
但是,您可以使用以下代码成功保存该文档:
NSFileWrapper *fileWrapper = [imageAttrString fileWrapperFromRange:NSMakeRange(0, [imageAttrString length]) documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType} error:&error];
[fileWrapper writeToURL:yourFileURL options:NSFileWrapperWritingAtomic originalContentsURL:nil error:&error];
Run Code Online (Sandbox Code Playgroud)
因为显然NSFileWrapper知道如何处理RTFD文档,而NSData却不知道其中包含什么。
但是,主要问题仍然存在-如何通过电子邮件发送?因为RTFD文档不是目录而是文件,所以我说它不太适合通过电子邮件发送,但是您可以压缩它并使用扩展名.rtfd.zip进行发送。扩展名是至关重要的,因为它将告诉Mail应用程序用户点击附件时如何显示附件的内容。实际上,它也可以在Gmail和iOS上的其他电子邮件应用程序中使用,因为UIWebView知道如何显示.rtfd.zip。这是关于它的技术说明:https : //developer.apple.com/library/ios/qa/qa1630/_index.html#//apple_ref/doc/uid/DTS40008749
因此,最重要的是-可以完成,但是RTFD文档将是电子邮件的附件,而不是电子邮件内容本身。如果您希望将其作为电子邮件内容,则可能应该考虑将图像嵌入HTML并以HTML格式发送邮件。
正如Andris提到的,Apple RTF实现不支持嵌入式图像。
RTFD并不是真正的选择,因为只有少数OS X应用程序可以打开RTFD文件。例如,MS Office无法。
在某些情况下,创建带有嵌入式图像的HTML文件可能会有所帮助,但是-例如-大多数电子邮件客户端不支持带有嵌入式图像的HTML(Apple Mail支持,但是Outlook不支持)。
但是幸运的是,有一种解决方案可以创建带有嵌入式图像的真实RTF文件!
由于RTF格式当然支持嵌入式图像(仅Apple实施不支持),因此可以将NSAttributedStrings(NSTextAttachments)中的图像(手动)编码到RTF流中。
以下类别完成了所有需要的工作:
/**
NSAttributedString (MMRTFWithImages)
*/
@interface NSAttributedString (MMRTFWithImages)
- (NSString *)encodeRTFWithImages;
@end
/**
NSAttributedString (MMRTFWithImages)
*/
@implementation NSAttributedString (MMRTFWithImages)
/*
encodeRTFWithImages
*/
- (NSString *)encodeRTFWithImages {
NSMutableAttributedString* stringToEncode = [[NSMutableAttributedString alloc] initWithAttributedString:self];
NSRange strRange = NSMakeRange(0, stringToEncode.length);
//
// Prepare the attributed string by removing the text attachments (images) and replacing them by
// references to the images dictionary
NSMutableDictionary* attachmentDictionary = [NSMutableDictionary dictionary];
while (strRange.length) {
// Get the next text attachment
NSRange effectiveRange;
NSTextAttachment* textAttachment = [stringToEncode attribute:NSAttachmentAttributeName
atIndex:strRange.location
effectiveRange:&effectiveRange];
strRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(strRange) - NSMaxRange(effectiveRange));
if (textAttachment) {
// Text attachment found -> store image to image dictionary and remove the attachment
NSFileWrapper* fileWrapper = [textAttachment fileWrapper];
UIImage* image = [[UIImage alloc] initWithData:[fileWrapper regularFileContents]];
// Kepp image size
UIImage* scaledImage = [self imageFromImage:image
withSize:textAttachment.bounds.size];
NSString* imageKey = [NSString stringWithFormat:@"_MM_Encoded_Image#%zi_", [scaledImage hash]];
[attachmentDictionary setObject:scaledImage
forKey:imageKey];
[stringToEncode removeAttribute:NSAttachmentAttributeName
range:effectiveRange];
[stringToEncode replaceCharactersInRange:effectiveRange
withString:imageKey];
strRange.length += [imageKey length] - 1;
} // if
} // while
//
// Create the RTF stream; without images but including our references
NSData* rtfData = [stringToEncode dataFromRange:NSMakeRange(0, stringToEncode.length)
documentAttributes:@{
NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType
}
error:NULL];
NSMutableString* rtfString = [[NSMutableString alloc] initWithData:rtfData
encoding:NSASCIIStringEncoding];
//
// Replace the image references with hex encoded image data
for (id key in attachmentDictionary) {
NSRange keyRange = [rtfString rangeOfString:(NSString*)key];
if (NSNotFound != keyRange.location) {
// Reference found -> replace with hex coded image data
UIImage* image = [attachmentDictionary objectForKey:key];
NSData* pngData = UIImagePNGRepresentation(image);
NSString* hexCodedString = [self hexadecimalRepresentation:pngData];
NSString* encodedImage = [NSString stringWithFormat:@"{\\*\\shppict {\\pict \\pngblip %@}}", hexCodedString];
[rtfString replaceCharactersInRange:keyRange withString:encodedImage];
}
}
return rtfString;
}
/*
imageFromImage:withSize:
Scales the input image to pSize
*/
- (UIImage *)imageFromImage:(UIImage *)pImage
withSize:(CGSize)pSize {
UIGraphicsBeginImageContextWithOptions(pSize, NO, 0.0);
[pImage drawInRect:CGRectMake(0, 0, pSize.width, pSize.height)];
UIImage* resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
/*
hexadecimalRepresentation:
Returns a hex codes string for all bytes in a NSData object
*/
- (NSString *) hexadecimalRepresentation:(NSData *)pData {
static const char* hexDigits = "0123456789ABCDEF";
NSString* result = nil;
size_t length = pData.length;
if (length) {
NSMutableData* tempData = [NSMutableData dataWithLength:(length << 1)]; // double length
if (tempData) {
const unsigned char* src = [pData bytes];
unsigned char* dst = [tempData mutableBytes];
if ((src) &&
(dst)) {
// encode nibbles
while (length--) {
*dst++ = hexDigits[(*src >> 4) & 0x0F];
*dst++ = hexDigits[(*src++ & 0x0F)];
} // while
result = [[NSString alloc] initWithData:tempData
encoding:NSASCIIStringEncoding];
} // if
} // if
} // if
return result;
}
@end
Run Code Online (Sandbox Code Playgroud)
基本思想来自本文。
| 归档时间: |
|
| 查看次数: |
3497 次 |
| 最近记录: |