• 浅析NSTextContainer


    浅析NSTextContainer

    TextKit中的NSTextContainer有点晦涩难懂,如果想用TextKit实现文本分页的效果,你是必须要使用NSTextContainer的......

    他们的关系是这样子的:

    NSTextStorage  ---> NSLayoutManager ---> 多个NSTextContainer

    当你添加了几个NSTextContainer的时候,对应的那个NSTextContainer实际上已经分页好了,下面用例子来验证结论:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        // 数据源
        NSString *string = [NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"bubizhidaowoshishui" withExtension:@"txt"] usedEncoding:nil
                                                       error:nil];
        
        // 文本容器
        NSTextStorage *storage = [[NSTextStorage alloc] initWithString:string];
        
        // 文本容器的布局管理器
        NSLayoutManager *layoutManager = [NSLayoutManager new];
        [storage addLayoutManager:layoutManager];
        
        // 分段显示文本容器中的内容
        CGSize size = CGSizeMake(300, 540);
        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];
        NSTextContainer *textContainer4 = [[NSTextContainer alloc] initWithSize:size];
        [layoutManager addTextContainer:textContainer4];
        
        // 给TextView添加带有内容和布局的容器
        UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 20,
                                                                            size.width, size.height)
                                                   textContainer:textContainer1];
        textView.layer.borderWidth = 1;
        textView.scrollEnabled     = NO;
        textView.editable          = NO;
        [self.view addSubview:textView];
        
        // 验证
        if (textView.textStorage == storage)
        {
            NSLog(@"textView.textStorage == storage");
        }
        
        if (textView.layoutManager == layoutManager)
        {
            NSLog(@"textView.layoutManager == layoutManager");
        }
        
        NSLog(@"计算的页码数:%f", [textView sizeThatFits:CGSizeMake(300, FLT_MAX)].height / 540.f);
    }

    注意看下面的关系:

    修改一下源码后,如下打印(注意将容器换成了textContainer2了):

    你会发现,textContainer2显示了第二页的内容,但是呢,你会发现整个UITextView的页码变成了119了.

    其实,看到这里,结论已经相当明显了.

    NSLayoutManager就像一个队列一样,它会将添加到NSLayoutManager中的NSTextContainer自动按照进入队列的顺序来给NSTextContainer赋值,最先进入队列的NSTextContainer将会有着最多显示的内容,往后进入队列的NSTextContainer会依次递减(发现这个花了我半天时间-_-!!).

    还有一点内容相当重要哦:)

    看起来,你可能觉得UITextView仅仅持有了一个NSTextContainer,其实,他还接管了你在上面定义的那个NSTextStorage以及layoutManager,这一点很容易被忽视掉得.

    也就是说(个人观点):

           UITextView在获取到了NSTextContainer后,会自动的接管了与这个NSTextContainer相关的所有配置,UITextView将自身包含的textStorage以及layoutManager替换成了NSTextContainer相关配置.

    附录:

    解析1.3M的txt文本.

    花了将近3.3s......

    拖动时占用内存的情况:

    这内存长的有点恐怖哦:)

  • 相关阅读:
    ios -- 教你如何轻松学习Swift语法(一)
    collectionView,tableView的细节处理
    主流界面搭建原理(类似百思不得姐主界面)
    ios--时间格式化(cell业务逻辑处理)
    test
    Mac下安装Matlab R2015b
    最大奇约数
    编码问题
    最优二叉查找树
    二维数组和二级指针
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3769863.html
Copyright © 2020-2023  润新知