iOS图文混排-模仿石墨文档文档编辑器(踩坑篇)

图文混排实现

最近公司的项目需要用到图文混排编辑来书写个人简介,由于需求功能比较简单,所以找到了SimpleWord,个人感觉功能还是很强大的,但在实现需求过程中发现了一些问题,特此记录一下。

踩坑

1、在web上正常加载的图片(图1),通过富文本的下面的方式显示在textView上会出现图片宽高不适配的情况,如图2所示;

textView.attributedText = [[NSAttributedString alloc] initWithData:[autoStr dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];

iOS图文混排-模仿石墨文档文档编辑器(踩坑篇)_第1张图片
图1 - web上显示的样式


iOS图文混排-模仿石墨文档文档编辑器(踩坑篇)_第2张图片
图1 - textView上显示的样式

2、由于图片都是网络图片,显示在textView上如果不对图片进行修改,点击保存,用SimpleWord写好的的方法将原生的 AttributedString 导出成 HTML的方式,会存在的问题。

填坑

1、针对第一个问题,我将得到的html加上img的css样式,代码如下,完美解决图片不适配的问题!

NSString *autoStr = [NSString stringWithFormat:@"%@",SCREENW - 2*20,_htmlString];

NSAttributedString *attributedText = [[NSAttributedString alloc] initWithData:[autoStr dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];

2、针对第二个问题,图片标签src="null"的问题,这个问题还是困惑了很久的,后来通过查看他将原生的 AttributedString 导出成 HTML的方法,由于代码较长,就贴出导出img的方法;

    可以分析得出导出img的思路是获取attributes中的NSAttachment类,在拿到NSAttachment的userInfo属性,但这个userInfo是NSAttachment的分类属性,我们转成attributedString时候并没有给他赋初值,所以直接对原来图片进行保存的话,肯定是没有值的!

NSDictionary *attributes = [attributedString attributesAtIndex:effectiveRange.location effectiveRange:&effectiveRange];

NSTextAttachment *attachment = attributes[@"NSAttachment"];

NSParagraphStyle *paragraph = attributes[@"NSParagraphStyle"];

LMParagraphConfig *paragraphConfig = [[LMParagraphConfig alloc] initWithParagraphStyle:paragraph type:LMParagraphTypeNone];

if (attachment) {

switch (attachment.attachmentType) {

case LMTextAttachmentTypeImage: // attachment.fileWrapper.preferredFilename

[htmlContent appendString:[NSString stringWithFormat:@"", attachment.userInfo]];

break;

default:

break;

}

}

找到问题之后,接下来就是解决了,现在要做的就是在原来attributedString的基础上取出NSTextAttachment,并给其userInfo属性赋上我们的图片地址;参照图片生成NSTextAttachment 的方法

- (NSTextAttachment *)insertImage:(UIImage *)image;

我们在得出修改后的富文本字符串之前,我们要先拿到所有的img标签,在这里我用的是Hpple。

+ (NSArray *)getSrcArrWithHtmlString:(NSString *)htmlString {

NSData *data =[htmlString dataUsingEncoding:NSUnicodeStringEncoding];

NSString *result = [[NSString alloc] initWithData:data  encoding:NSUTF8StringEncoding];  //data转字符串 为了打印不是乱码

SLog(@"------%@",result);

TFHpple *Hpple = [[TFHpple alloc]initWithHTMLData:data];

NSArray *array =[Hpple searchWithXPathQuery:@"//img"]; //获取到为img标签数组

NSMutableArray *secArr = [NSMutableArray array];

for (TFHppleElement *HppleElement in array) {

NSDictionary *node = HppleElement.attributes;

[secArr addObject:node[@"src"]];

}

return secArr;

}


最后,我们可以得出修改后的富文本字符串,大致代码如下;

// 改变attachment.userInfo

+ (NSAttributedString *)attStringFromAttributedString:(NSAttributedString *)attributedString textView:(UITextView *)textView htmlString:(NSString *)htmlString {

NSMutableAttributedString *copyAttr = [[NSMutableAttributedString alloc] initWithAttributedString:attributedString];

NSRange effectiveRange = NSMakeRange(0, 0);

int section = 0;

NSArray *secArr = [self getSrcArrWithHtmlString:htmlString];

while (effectiveRange.location + effectiveRange.length < attributedString.length) {

NSDictionary *attributes = [attributedString attributesAtIndex:effectiveRange.location effectiveRange:&effectiveRange];

NSTextAttachment *attachment = attributes[@"NSAttachment"];

if (attachment) {

attachment.attachmentType = LMTextAttachmentTypeImage;

attachment.userInfo = secArr[section]; // 获取网络图片路径

section++;

//

NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];

NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:@"\n"];

[attributedStr insertAttributedString:attachmentString atIndex:0];

[attributedStr addAttributes:textView.typingAttributes range:NSMakeRange(0, attributedStr.length)];

// 添加样式

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];

[paragraphStyle setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];

paragraphStyle.paragraphSpacingBefore = 8.f;

paragraphStyle.paragraphSpacing = 8.f;

[attributedStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, attributedStr.length)];

[copyAttr replaceCharactersInRange:effectiveRange withAttributedString:attributedStr];

}

effectiveRange = NSMakeRange(effectiveRange.location + effectiveRange.length, 0);

}

return copyAttr;

}


PS:由于我这次项目只是简单的图文编辑跟混排,需要的内容不是很多,所以采用NSAttributedString进行展示,如果需要大量的图片及文字展示,例如阅读类的APP,建议还是用coreText或textKit进行排版!

你可能感兴趣的:(iOS图文混排-模仿石墨文档文档编辑器(踩坑篇))