测试TextKit渲染大文本的效率
TextKit可以用来做精美的电子书,而电子书通常都是txt格式的,那么渲染txt格式的文本的效率如何呢?
以下来进行测试.
#import "RootViewController.h" #import "FontPool.h" #import "YXGCD.h" @interface RootViewController ()<NSLayoutManagerDelegate> @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor blackColor]; [[GCDQueue globalQueue] execute:^{ NSLog(@"start"); // 数据源 NSString *string = [NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"bubizhidaowoshishui" withExtension:@"txt"] usedEncoding:nil error:nil]; // 文本容器 NSTextStorage *storage = [[NSTextStorage alloc] initWithString:string]; // 段落属性 NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineHeightMultiple = 1.f; // 可变行高,乘因数 paragraphStyle.lineSpacing = 5.f; // 行间距 paragraphStyle.minimumLineHeight = 10.f; // 最小行高 paragraphStyle.maximumLineHeight = 20.f; // 最大行高 paragraphStyle.paragraphSpacing = 10.f; // 段间距 paragraphStyle.alignment = NSTextAlignmentLeft; // 对齐方式 paragraphStyle.firstLineHeadIndent = 30.f; // 段落首文字离边缘间距 paragraphStyle.headIndent = 0.f; // 段落除了第一行的其他文字离边缘间距 paragraphStyle.tailIndent = 0.f; // ??????? [storage addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, storage.string.length)]; // 字体属性 [storage addAttribute:NSFontAttributeName value:[UIFont fontWithName:CUSTOM_FONT(@"新蒂小丸子体", 0) size:15.f] range:NSMakeRange(0, storage.string.length)]; [storage addAttribute:NSForegroundColorAttributeName value:[UIColor cyanColor] range:NSMakeRange(0, storage.string.length)]; [[GCDQueue mainQueue] execute:^{ // 文本容器的布局管理器 NSLayoutManager *layoutManager = [NSLayoutManager new]; NSLog(@"step 1"); // 开始渲染 [storage addLayoutManager:layoutManager]; NSLog(@"step 2"); // 分段显示文本容器中的内容 CGSize size = CGSizeMake(300, 520); NSTextContainer *textContainer1 = [[NSTextContainer alloc] initWithSize:size]; [layoutManager addTextContainer:textContainer1]; NSTextContainer *textContainer2 = [[NSTextContainer alloc] initWithSize:size]; [layoutManager addTextContainer:textContainer2]; NSTextContainer *textContainer3 = [[NSTextContainer alloc] initWithSize:size]; [layoutManager addTextContainer:textContainer3]; NSLog(@"step - 3"); UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 20, size.width, size.height + 20) textContainer:textContainer1]; textView.layer.borderWidth = 1; textView.scrollEnabled = NO; textView.backgroundColor = [UIColor clearColor]; textView.editable = NO; [self.view addSubview:textView]; NSLog(@"step - 4"); }]; }]; } @end
测试的文本为310K大小
以下是测试结果:
2014-06-06 08:31:00.406 TextKit[4922:1803] start
2014-06-06 08:31:00.437 TextKit[4922:60b] step 1
2014-06-06 08:31:01.374 TextKit[4922:60b] step 2
2014-06-06 08:31:01.376 TextKit[4922:60b] step - 3
2014-06-06 08:31:02.211 TextKit[4922:60b] step - 4
从结果中,我们能发现一个规律哦:
当storage添加layoutManager的时候,此时就已经开始进行一些计算处理了,当我把[storage addLayoutManager:layoutManager];移动到子线程中运行的时候,就会发现后面的UITextView渲染不出文本了,这很容易理解,因为,只有在UI线程(主线程)中执行了渲染操作才会被显示出来,所以,NSTextStorage在添加NSLayoutManager的时候,就已经开始进行布局渲染了.310k的文本花了将近1秒.加上后面的UITextView加载又花了将近1秒,总共花了将近2秒......
也就是说,渲染300k的文本会在主线程上阻塞2秒的时间,这个延时感用户很难接受吧.....
有没有什么解决方案呢?
除了把txt文档分割小一点,别无他法哦,至少我目前没有想到好的方法.