iOS圖文混排-模仿石墨文檔文檔編輯器(踩坑篇)

圖文混排實現(xiàn)

最近公司的項目需要用到圖文混排編輯來書寫個人簡介,由于需求功能比較簡單,所以找到了SimpleWord,個人感覺功能還是很強大的,但在實現(xiàn)需求過程中發(fā)現(xiàn)了一些問題,特此記錄一下。

踩坑

1、在web上正常加載的圖片(圖1),通過富文本的下面的方式顯示在textView上會出現(xiàn)圖片寬高不適配的情況,如圖2所示;

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

圖1 - web上顯示的樣式


圖1 - textView上顯示的樣式

2、由于圖片都是網(wǎng)絡(luò)圖片,顯示在textView上如果不對圖片進行修改,點擊保存,用SimpleWord寫好的的方法將原生的 AttributedString 導(dǎo)出成 HTML的方式,會存在<img src="null"/>的問題。

填坑

1、針對第一個問題,我將得到的html加上img的css樣式,代碼如下,完美解決圖片不適配的問題!

NSString *autoStr = [NSString stringWithFormat:@"<head><style>img{width:%f !important;height:auto}</style></head>%@",SCREENW - 2*20,_htmlString];

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

2、針對第二個問題,圖片標簽src="null"的問題,這個問題還是困惑了很久的,后來通過查看他將原生的 AttributedString 導(dǎo)出成 HTML的方法,由于代碼較長,就貼出導(dǎo)出img的方法;

? ? 可以分析得出導(dǎo)出img的思路是獲取attributes中的NSAttachment類,在拿到NSAttachment的userInfo屬性,但這個userInfo是NSAttachment的分類屬性,我們轉(zhuǎn)成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:@"<img src=\"%@\" width=\"100%%\"/>", attachment.userInfo]];

break;

default:

break;

}

}

找到問題之后,接下來就是解決了,現(xiàn)在要做的就是在原來attributedString的基礎(chǔ)上取出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轉(zhuǎn)字符串 為了打印不是亂碼

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

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

NSArray *array =[Hpple searchWithXPathQuery:@"http://img"]; //獲取到為img標簽數(shù)組

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]; // 獲取網(wǎng)絡(luò)圖片路徑

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:由于我這次項目只是簡單的圖文編輯跟混排,需要的內(nèi)容不是很多,所以采用NSAttributedString進行展示,如果需要大量的圖片及文字展示,例如閱讀類的APP,建議還是用coreText或textKit進行排版!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容