淺析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......

 

拖動時占用內存的情況:

這內存長的有點恐怖哦:)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM