iOS开发中App端编辑器实现思路

作者: 梁森的简书 | 来源:发表于2019-01-25 16:35 被阅读20次

笔记类App:


笔记App.jpg

我们在使用笔记类App的时候使用到的核心功能就是编辑器。


编辑器.jpg

编辑器实现的难点1(对于本人来说):插入图片

编辑器使用的是一个UITextView,那么如何往UITextView中插入图片呢?

往UITextView插入图片

在自定义的UITextView插入图片代码:

  #pragma mark --- 插入图片关键代码
- (void)setImage:(UIImage *)image {
NSLog(@"选择图片...");
if (image == nil) {
    [self becomeFirstResponder];
    return;
}

CGFloat width = self.frame.size.width-self.textContainer.lineFragmentPadding*2;

NSMutableAttributedString *mAttributedString = self.attributedText.mutableCopy;
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.bounds = CGRectMake(0, 0, width, width * image.size.height / image.size.width);
attachment.image = image;

NSMutableAttributedString *attachmentString = [[NSMutableAttributedString alloc] initWithAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]];
[attachmentString addAttributes:[NSMutableDictionary dictionary] range:NSMakeRange(0, attachmentString.length)];

[mAttributedString insertAttributedString:attachmentString atIndex:NSMaxRange(self.selectedRange)];
//更新attributedText
NSInteger location = NSMaxRange(self.selectedRange) + 1;
self.attributedText = mAttributedString.copy;

//回复焦点
self.selectedRange = NSMakeRange(location, 0);
[self becomeFirstResponder];
}

在UITextView中插入图片的时候用到了NSTextAttachment这个类。

编辑器实现的难点二:将编辑器中的内容上传到远程服务器上

如果编辑器中的内容只是文字,那么很容易将编辑器中的内容上传到远程服务器。那么如果编辑器中的内容还有图片的话就不能按照只是文字的方式进行上传了。而当UITextView中的内容是富文本的时候,要想将编辑器中的内容上传到远程服务器需要先将其转换成html字符串。

将富文本转成html字符串的代码:

  + (void)sync_htmlStringWithAttributedText:(NSAttributedString *)attributedText
                          orignalHtml:(NSString *)orignalHtml
                 andCompletionHandler:(void (^)(NSString *html))handler {
if (attributedText.length == 0) {
    handler(nil);
    return;
}

NSMutableString *html = [NSMutableString string];
NSString *string = attributedText.string;

//保存UIImage数组
NSMutableArray *images = [NSMutableArray array];
//获取html中的图片地址数组
NSArray *imageUrls = [self imageUrls:orignalHtml];

[attributedText enumerateAttributesInRange:NSMakeRange(0, attributedText.length) options:(NSAttributedStringEnumerationLongestEffectiveRangeNotRequired) usingBlock:^(NSDictionary<NSAttributedStringKey,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
    NSString *selectString = [string substringWithRange:range];
    
    if ([selectString isEqualToString:ImagePlaceholderTag]) {
        NSTextAttachment *attachment = attrs[NSAttachmentAttributeName];
        if (attachment.image) {
            [html appendFormat:@"<img src='[image%ld]' />", images.count];
            [images addObject:attachment.image];
        } else {
            NSString *imageName = [[attachment.fileWrapper.preferredFilename stringByDeletingPathExtension] stringByDeletingPathExtension];
            for (NSString *imageUrl in imageUrls) {
                if ([imageUrl containsString:imageName]) {
                    [html appendFormat:@"<img src='%@' />", imageUrl];
                }
            }
        }
    }
    else if ([selectString isEqualToString:@"\n"]) {
        [html appendString:selectString];
    }
    else {
        UIFont *font = attrs[NSFontAttributeName];
        //字色 16进制
        NSString *textColor = [self hexStringFromColor:attrs[NSForegroundColorAttributeName]];
        //字号
        CGFloat fontSize = [font.fontDescriptor.fontAttributes[UIFontDescriptorSizeAttribute] floatValue];
        CGFloat location = html.length;
        [html appendFormat:@"<span style=\"color:%@; font-size:%.0fpx;\">%@</span>", textColor, fontSize, selectString];
        
        //斜体
        if ([attrs.allKeys containsObject:NSObliquenessAttributeName]) {
            [html insertString:@"<i>" atIndex:location];
            [html appendString:@"</i>"];
        }
        //下划线
        if ([attrs.allKeys containsObject:NSUnderlineColorAttributeName]) {
            [html insertString:@"<u>" atIndex:location];
            [html appendString:@"</u>"];
        }
        //粗体
        if ((font.fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) > 0) {
            [html insertString:@"<b>" atIndex:location];
            [html appendString:@"</b>"];
        }
    }
}];

[html replaceOccurrencesOfString:@"\n" withString:@"<br/>" options:0 range:NSMakeRange(0, html.length)];
[html replaceOccurrencesOfString:@"null" withString:@"" options:0 range:NSMakeRange(0, html.length)];

handler(html);


  #warning  将图片上传,获取图片地址,然后把图片地址写入html中, 替换成自己的图片请求

//    if (images.count) {
  //        //上传图片
  //        [self loadImages:images     andCompletionHandler:^(NSArray *names) {
//            //占位符  替换成  图片地址
//            for (int i=0; i<names.count; i++) {
//                [html replaceOccurrencesOfString:[NSString     stringWithFormat:@"[image%d]", i] withString:names[i] options:      (NSLiteralSearch) range:NSMakeRange(0, html.length)];
//            }
//            handler(html);
//        }];
//    } else {
    //        handler(html);
//    }
 }

编辑器实现的难点三:从远程服务器上获取编辑器的内容并显示出来

我们给远程服务器上传的是html字符串,那么我们下次从远程服务器上获取的也是html字符串,那么我们如何将html字符串以正确的形式显示在App上呢?此时需要先将html字符串转换成富文本。
将html字符串转换成富文本的代码:

  + (NSAttributedString *)attributedTextWithHtmlString:(NSString *)htmlString andImageWidth:(CGFloat)width {
NSData *data = [htmlString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dic = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                      NSCharacterEncodingDocumentOption: @(NSUTF8StringEncoding)};
NSAttributedString *attributedString = [[NSAttributedString alloc]
                                        initWithData:data options:dic
                                        documentAttributes:nil error:nil];

//斜体适配
NSMutableAttributedString *mAttributedString = attributedString.mutableCopy;
[mAttributedString enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, mAttributedString.length) options:(NSAttributedStringEnumerationLongestEffectiveRangeNotRequired) usingBlock:^(id  _Nullable value, NSRange range, BOOL * _Nonnull stop) {
    
    if ([value isKindOfClass:[UIFont class]]) {
        if ([[value description] containsString:@"italic"]) {
            [mAttributedString addAttribute:NSObliquenessAttributeName value:@0.3 range:range];
        }
    }
}];

//为了调整图片尺寸 需要在图片名后面拼接有图片宽高 例如:img-880x568.jpg
[mAttributedString enumerateAttribute:NSAttachmentAttributeName inRange:NSMakeRange(0, mAttributedString.length) options:(NSAttributedStringEnumerationLongestEffectiveRangeNotRequired) usingBlock:^(id  _Nullable value, NSRange range, BOOL * _Nonnull stop) {
    
    if ([value isKindOfClass:[NSTextAttachment class]]) {
        NSTextAttachment *attachment = value;
        NSString *imageName = [[attachment.fileWrapper.preferredFilename stringByDeletingPathExtension] stringByDeletingPathExtension];
        NSArray *sizeArr = [[imageName componentsSeparatedByString:@"-"].lastObject componentsSeparatedByString:@"x"];
        if (sizeArr.count == 2) {
            CGFloat width0 = [sizeArr[0] floatValue];
            CGFloat height0 = [sizeArr[1] floatValue];
            attachment.bounds = CGRectMake(0, 0, width, width * height0 / width0);
            ;
            //NSLog(@"%@:%@", imageName, NSStringFromCGRect(attachment.bounds));
        } else {
            attachment.bounds = CGRectMake(0, 0, width, width * 0.5);
        }
    }
}];
return mAttributedString.copy;
}

简单编辑器编辑效果图:


GIF.gif

demo地址:***https://gitee.com/liangsenliangsen/bi.git

本篇文章到这里就结束了,愿大家加班不多工资多,男同胞都有女朋友,女同胞都有男朋友。😊

相关文章

网友评论

    本文标题:iOS开发中App端编辑器实现思路

    本文链接:https://www.haomeiwen.com/subject/khomjqtx.html