ios markdown 解析_iOS开发中的Markdown渲染

iOS开发中的Markdown渲染

BearyChat的消息是全面支持Markdown语法的,所以在开发BearyChat的iOS客户端的时候需要处理Markdown的渲染。

主要是两套实现方案:

直接将Markdown文本转换成NSAttributedString。

先将Markdown文本转换成HTML,再将HTML转换成NSAttributedString。

方案2可用的第三方库相对多一些:

将HTML转换成NSAttributedString,在iOS 7之后UIKit为NSAttributedString增加了initWithData:options:documentAttributes:error:方法可以直接转换:

但是实测发现,这个方法的计算速度非常慢!google了一下,貌似因为这个方法渲染的过程是需要初始化ScriptCore的,每次渲染都要初始化一个ScriptCore肯定是不能忍的。

第三方库的替代方案:DTCoreText,NSAttributedString-DDHTML。二者之中,DTCoreText是一个比较成熟的第三方库,对样式的控制也比较灵活。

所以最终选择的方案是:首先用GHMarkdownParser讲Markdown转换成HTML,之后再用DTCoreText讲HTML转换成NSAttributedString最后交给UILabel等控件渲染。

最终的实现代码就比较简单了:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

#import

#import

@interface MarkdownParser

@property GHMarkdownParser *htmlParser;

@property (nonatomic, copy) NSDictionary *DTCoreText_options;

- (NSAttributedString *)DTCoreText_attributedStringFromMarkdown:(NSString *)text;

@end

@implementation MarkdownParser

- (instancetype)init {

self = [super init];

if (self) {

_htmlParser = [[GHMarkdownParser alloc] init];

_htmlParser.options = kGHMarkdownAutoLink;

_htmlParser.githubFlavored = YES;

}

return self;

}

- (NSString *)htmlFromMarkdown:(NSString *)text {

return [self.htmlParser HTMLStringFromMarkdownString:text];

}

- (NSAttributedString *)attributedStringFromMarkdown:(NSString *)text {

NSString *html = [self htmlFromMarkdown:text];

NSData *data = [html dataUsingEncoding:NSUTF8StringEncoding];

NSMutableAttributedString *attributed = [[NSMutableAttributedString alloc] initWithHTMLData:data options:self.DTCoreText_options documentAttributes:nil];

return attributed;

}

- (NSDictionary *)DTCoreText_options {

if (!_DTCoreText_options) {

_DTCoreText_options = @{

DTUseiOS6Attributes:@YES,

DTIgnoreInlineStylesOption:@YES,

DTDefaultLinkDecoration:@NO,

DTDefaultLinkColor:[UIColor blueColor],

DTLinkHighlightColorAttribute:[UIColor redColor],

DTDefaultFontSize:@15,

DTDefaultFontFamily:@"Helvetica Neue",

DTDefaultFontName:@"HelveticaNeue-Light"

};

}

return _DTCoreText_options;

}

@end

到这里,绝大部分的问题都解决了,还有一点点小问题:把解析得到的NSAttributedString丢给UILabel的attributedString渲染的时候,在options里设置的链接的颜色是无效的,貌似UILabel对链接的渲染颜色是不可改的。继续寻找替代方案:用第三方的TTTAttributedLabel代替UILabel。TTTAttributedLabel是UILabel的派生类,为UILabel提供了更多对NSAttributedString的控制。通过为TTTAttributedLabel设置超链接的样式最终解决了Markdown渲染的相关问题。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

#import

#import

@interface MarkdownLabel : TTTAttributedLabel

- (void)setDisplayedAttributedString:(id)text;

@end

@implementation MarkdownLabel

- (instancetype)initWithCoder:(NSCoder *)aDecoder {

self = [super initWithCoder:aDecoder];

if (self) {

[self commonConfig];

}

return self;

}

- (instancetype)initWithFrame:(CGRect)frame {

self = [super initWithFrame:frame];

if (self) {

[self commonConfig];

}

return self;

}

- (void)commonConfig {

self.delegate = self;

NSDictionary *linkAttributes = @{

(id)kCTForegroundColorAttributeName:[UIColor blueColor],

NSUnderlineStyleAttributeName:@(kCTUnderlineStyleNone),

NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue-Light" size:15]

};

self.linkAttributes = linkAttributes;

self.enabledTextCheckingTypes = 0;

}

- (void)setDisplayedAttributedString:(id)text {

NSMutableArray *linksAndRange = [@[] mutableCopy];

[self setText:[text string] afterInheritingLabelAttributesAndConfiguringWithBlock:^NSMutableAttributedString *(NSMutableAttributedString *mutableAttributedString) {

[text enumerateAttributesInRange:NSMakeRange(0, [text length])

options:0

usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {

if (attrs[NSLinkAttributeName]) {

[linksAndRange addObject:@[attrs[NSLinkAttributeName], [NSValue valueWithRange:range]]];

} else {

[mutableAttributedString addAttributes:attrs range:range];

}

}];

return mutableAttributedString;

}];

for (NSArray *pair in linksAndRange) {

[self addLinkToURL:pair[0] withRange:[pair[1] rangeValue]];

}

}

@end

http://nightfade.github.io/2015/06/26/ios-markdown-rendering/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值